wake-up-neo.com

Erstellen Sie Dummys aus einer Spalte mit mehreren Werten in Pandas

Ich suche nach einer Pythonic-Methode, um das folgende Problem zu lösen.

Die pandas.get_dummies()-Methode eignet sich hervorragend zum Erstellen von Dummys aus einer kategorialen Spalte eines Datenrahmens. Wenn die Spalte beispielsweise Werte in ['A', 'B'] enthält, erstellt get_dummies() 2 Dummy-Variablen und weist 0 oder 1 entsprechend zu.

Jetzt muss ich mit dieser Situation fertig werden. Eine einzelne Spalte, nennen wir sie 'label', hat Werte wie ['A', 'B', 'C', 'D', 'A*C', 'C*D']. get_dummies() erstellt 6 Dummys, aber ich möchte nur 4 davon, so dass eine Reihe mehrere 1s haben kann. 

Gibt es eine Möglichkeit, pythonisch damit umzugehen? Ich könnte mir nur einen Schritt-für-Schritt-Algorithmus vorstellen, um ihn zu bekommen, aber dazu würde get_dummies () nicht gehören. Vielen Dank

Editiert, hoffe es wird klarer!

24
mkln

Ich weiß, es ist eine Weile her, seit diese Frage gestellt wurde, aber es gibt (zumindest now gibt es) einen Einzeiler, der von der Dokumentation unterstützt wird: /:

In [4]: df
Out[4]:
      label
0  (a, c, e)
1     (a, d)
2       (b,)
3     (d, e)

In [5]: df['label'].str.join(sep='*').str.get_dummies(sep='*')
Out[5]:
   a  b  c  d  e
0  1  0  1  0  1
1  1  0  0  1  0
2  0  1  0  0  0
3  0  0  0  1  1
53
offbyone

Ich habe eine etwas sauberere Lösung. Angenommen, wir möchten den folgenden Datenrahmen transformieren

   pageid category
0       0        a
1       0        b
2       1        a
3       1        c

in

        a  b  c
pageid         
0       1  1  0
1       1  0  1

Eine Möglichkeit ist, den DictVectorizer von scikit-learn zu verwenden. Ich würde jedoch gerne andere Methoden kennenlernen.

df = pd.DataFrame(dict(pageid=[0, 0, 1, 1], category=['a', 'b', 'a', 'c']))

grouped = df.groupby('pageid').category.apply(lambda lst: Tuple((k, 1) for k in lst))
category_dicts = [dict(tuples) for tuples in grouped]
v = sklearn.feature_extraction.DictVectorizer(sparse=False)
X = v.fit_transform(category_dicts)

pd.DataFrame(X, columns=v.get_feature_names(), index=grouped.index)
5
ariddell

Sie können den Dummies-Datenrahmen mit Ihren Rohdaten generieren, die Spalten, die ein bestimmtes Atom enthalten, isolieren und die Ergebnisübereinstimmungen anschließend wieder in der Atomsäule speichern.

df
Out[28]: 
  label
0     A
1     B
2     C
3     D
4   A*C
5   C*D

dummies = pd.get_dummies(df['label'])

atom_col = [c for c in dummies.columns if '*' not in c]

for col in atom_col:
    ...:     df[col] = dummies[[c for c in dummies.columns if col in c]].sum(axis=1)
    ...:     

df
Out[32]: 
  label  A  B  C  D
0     A  1  0  0  0
1     B  0  1  0  0
2     C  0  0  1  0
3     D  0  0  0  1
4   A*C  1  0  1  0
5   C*D  0  0  1  1
4
Boud

Ich glaube, diese Frage braucht eine aktualisierte Antwort, nachdem sie auf den MultiLabelBinarizer von sklearn gestoßen ist.

Die Verwendung davon ist so einfach wie ...

# Instantiate the binarizer
mlb = MultiLabelBinarizer()

# Using OP's original data frame
df = pd.DataFrame(data=['A', 'B', 'C', 'D', 'A*C', 'C*D'], columns=["label"])

print(df)
  label
0     A
1     B
2     C
3     D
4   A*C
5   C*D

# Convert to a list of labels
df = df.apply(lambda x: x["label"].split("*"), axis=1)

print(df)
0       [A]
1       [B]
2       [C]
3       [D]
4    [A, C]
5    [C, D]
dtype: object

# Transform to a binary array
array_out = mlb.fit_transform(df)

print(array_out)
[[1 0 0 0]
 [0 1 0 0]
 [0 0 1 0]
 [0 0 0 1]
 [1 0 1 0]
 [0 0 1 1]]

# Convert back to a dataframe (unnecessary step in many cases)
df_out = pd.DataFrame(data=array_out, columns=mlb.classes_)

print(df_out)
   A  B  C  D
0  1  0  0  0
1  0  1  0  0
2  0  0  1  0
3  0  0  0  1
4  1  0  1  0
5  0  0  1  1

Dies ist auch sehr schnell, es dauerte praktisch keine Zeit (0,03 Sekunden) über 1000 Zeilen und 50.000 Klassen.

0
Chris Farr