2013-08-02 5 views
7

Ich versuche, einige lineare Regressionsanalyse durchzuführen, habe ich einige kategorische Funktionen, die ich in Dummy-Variablen mit dem super tollen get_dummies konvertieren.Get Subset der häufigsten Dummy-Variablen in Pandas

Das Problem, dem ich gegenüberstehe, ist, dass der Datenrahmen zu groß wird, wenn ich alle Elemente der Kategorien hinzufüge.

Gibt es einen Weg (mit get_dummies oder einer ausgefeilteren Methode), nur Dummy-Variablen der häufigsten Begriffe statt aller zu erstellen?

Antwort

0

Sie könnten erste value_counts verwenden, um zu sehen, welche die am häufigsten sind:

In [11]: s = pd.Series(list('aabccc')) 

In [12]: s 
Out[12]: 
0 a 
1 a 
2 b 
3 c 
4 c 
5 c 
dtype: object 

In [13]: s.value_counts() 
Out[13]: 
c 3 
a 2 
b 1 
dtype: int64 

Die Werte, die die am wenigsten häufig sind (zB alle mit Ausnahme der ersten zwei):

In [14]: s.value_counts().index[2:] 
Out[14]: Index([u'b'], dtype=object) 

Sie können einfach replace all diesen Vorkommnissen mit NaN:

In [15]: s1 = s.replace(s.value_counts().index[2:], np.nan) 

In [16]: s1 
Out[16]: 
0  a 
1  a 
2 NaN 
3  c 
4  c 
5  c 
dtype: object 

und führen get_dummies (was ich denke, sollte die NaN, aber es ist ein Fehler, daher der notnull Hack ignorieren):

In [16]: pd.get_dummies(s1[s1.notnull()]) 
Out[16]: 
    a c 
0 1 0 
1 1 0 
3 0 1 
4 0 1 
5 0 1 

Wenn Sie diese Ergebnisse einschließen wollten Sie einen anderen Platzhalter verwenden könnte (z.B '_').

+0

Oh, es sieht so aus, als gäbe es einen Fehler in 'get_dummies', es ignoriert nicht das NaN, sondern macht etwas Seltsames ... –

5

Verwendung value_counts() die Frequenzzählung zu tun, und dann eine Maske für die Zeilen erstellen, die Sie bleiben wollen:

import pandas as pd 
values = pd.Series(["a","b","a","b","c","d","e","a"]) 
counts = pd.value_counts(values) 
mask = values.isin(counts[counts > 1].index) 
print pd.get_dummies(values[mask]) 

Ausgang:

a b 
0 1 0 
1 0 1 
2 1 0 
3 0 1 
7 1 0 

, wenn Sie die Daten alle wollen:

values[~mask] = "-" 
print pd.get_dummies(values) 

Ausgabe:

- a b 
0 0 1 0 
1 0 0 1 
2 0 1 0 
3 0 0 1 
4 1 0 0 
5 1 0 0 
6 1 0 0 
7 0 1 0 
0

habe ich die Antwort, dass @HYRY gab eine Funktion zu schreiben, die einen Parameter (Schwelle) haben, die verwendet werden können, um die gesuchten Werten und unbeliebt zu trennen (kombiniert in ‚anderen‘ Spalte).

import pandas as pd 
import numpy as np 

# func that returns a dummified DataFrame of significant dummies in a given column 
def dum_sign(dummy_col, threshold=0.1): 

    # removes the bind 
    dummy_col = dummy_col.copy() 

    # what is the ratio of a dummy in whole column 
    count = pd.value_counts(dummy_col)/len(dummy_col) 

    # cond whether the ratios is higher than the threshold 
    mask = dummy_col.isin(count[count > threshold].index) 

    # replace the ones which ratio is lower than the threshold by a special name 
    dummy_col[~mask] = "others" 

    return pd.get_dummies(dummy_col, prefix=dummy_col.name) 
# 

Lassen Sie uns einige Daten erstellen:

df = ['a', 'a', np.nan, np.nan, 'a', np.nan, 'a', 'b', 'b', 'b', 'b', 'b', 
      'c', 'c', 'd', 'e', 'g', 'g', 'g', 'g'] 

data = pd.Series(df, name='dums') 

Beispiele:

In: dum_sign(data) 
Out: 
    dums_a dums_b dums_g dums_others 
0  1  0  0   0 
1  1  0  0   0 
2  0  0  0   1 
3  0  0  0   1 
4  1  0  0   0 
5  0  0  0   1 
6  1  0  0   0 
7  0  1  0   0 
8  0  1  0   0 
9  0  1  0   0 
10  0  1  0   0 
11  0  1  0   0 
12  0  0  0   1 
13  0  0  0   1 
14  0  0  0   1 
15  0  0  0   1 
16  0  0  1   0 
17  0  0  1   0 
18  0  0  1   0 
19  0  0  1   0 

In: dum_sign(data, threshold=0.2) 
Out: 
    dums_b dums_others 
0  0   1 
1  0   1 
2  0   1 
3  0   1 
4  0   1 
5  0   1 
6  0   1 
7  1   0 
8  1   0 
9  1   0 
10  1   0 
11  1   0 
12  0   1 
13  0   1 
14  0   1 
15  0   1 
16  0   1 
17  0   1 
18  0   1 
19  0   1 

In: dum_sign(data, threshold=0) 
Out: 
    dums_a dums_b dums_c dums_d dums_e dums_g dums_others 
0  1  0  0  0  0  0   0 
1  1  0  0  0  0  0   0 
2  0  0  0  0  0  0   1 
3  0  0  0  0  0  0   1 
4  1  0  0  0  0  0   0 
5  0  0  0  0  0  0   1 
6  1  0  0  0  0  0   0 
7  0  1  0  0  0  0   0 
8  0  1  0  0  0  0   0 
9  0  1  0  0  0  0   0 
10  0  1  0  0  0  0   0 
11  0  1  0  0  0  0   0 
12  0  0  1  0  0  0   0 
13  0  0  1  0  0  0   0 
14  0  0  0  1  0  0   0 
15  0  0  0  0  1  0   0 
16  0  0  0  0  0  1   0 
17  0  0  0  0  0  1   0 
18  0  0  0  0  0  1   0 
19  0  0  0  0  0  1   0 

Irgendwelche Vorschläge, wie nans behandeln? Ich glaube, dass Nans nicht als "andere" behandelt werden sollten.

UPD: Ich habe es auf einem ziemlich großen Datensatz (5 mil Obs) mit 183 verschiedenen Strings in der Spalte getestet, die ich dummy machen wollte. Die Implementierung dauert maximal 10 Sekunden auf meinem Laptop.