Colonne categoriche di conversione di massa in panda (non codifica a caldo)


12

Ho un frame di dati Panda con tonnellate di colonne categoriche, che sto pianificando di utilizzare nell'albero decisionale con scikit-learn. Devo convertirli in valori numerici (non un vettore caldo). Posso farlo con LabelEncoder di scikit-learn. Il problema è che ce ne sono troppi e non voglio convertirli manualmente.

Quale sarebbe un modo semplice per automatizzare questo processo.


La funzione get_dummies in Panda può aiutarti. Controlla la documentazione qui per maggiori dettagli . Penso che copra perfettamente questo caso d'uso e puoi modificare ulteriormente il comportamento fornendo prefissi personalizzati.
hssay,

Risposte:


11

Se le tue colonne categoriali sono attualmente carattere / oggetto, puoi usare qualcosa del genere per fare ognuna:

char_cols = df.dtypes.pipe(lambda x: x[x == 'object']).index

for c in char_cols:
    df[c] = pd.factorize(df[c])[0]

Se devi essere in grado di tornare alle categorie, creerei un dizionario per salvare la codifica; qualcosa di simile a:

char_cols = df.dtypes.pipe(lambda x: x[x == 'object']).index
label_mapping = {}

for c in char_cols:
    df[c], label_mapping[c] = pd.factorize(df[c])

Usando il mcve di Julien si otterrà:

In [3]: print(df)
Out[3]: 
    a   b   c   d
0   0   0   0   0.155463
1   1   1   1   0.496427
2   0   0   2   0.168625
3   2   0   1   0.209681
4   0   2   1   0.661857

In [4]: print(label_mapping)
Out[4]:
{'a': Index(['Var2', 'Var3', 'Var1'], dtype='object'),
 'b': Index(['Var2', 'Var1', 'Var3'], dtype='object'),
 'c': Index(['Var3', 'Var2', 'Var1'], dtype='object')}

Il tuo codice per trovare le objectcolonne è molto utile.
javadba,

6

Innanzitutto, creiamo un mcve con cui giocare:

import pandas as pd
import numpy as np

In [1]: categorical_array = np.random.choice(['Var1','Var2','Var3'],
                                             size=(5,3), p=[0.25,0.5,0.25])
        df = pd.DataFrame(categorical_array,
               columns=map(lambda x:chr(97+x), range(categorical_array.shape[1])))
        # Add another column that isn't categorical but float
        df['d'] = np.random.rand(len(df))
        print(df)

Out[1]:
      a     b     c         d
0  Var3  Var3  Var3  0.953153
1  Var1  Var2  Var1  0.924896
2  Var2  Var2  Var2  0.273205
3  Var2  Var1  Var3  0.459676
4  Var2  Var1  Var1  0.114358

Ora possiamo usare pd.get_dummies per codificare le prime tre colonne.

Nota che sto usando il drop_firstparametro perché i N-1manichini sono sufficienti per descrivere appieno le Npossibilità (es: se a_Var2e a_Var3sono 0, allora è a_Var1). Inoltre, sto specificando specificamente le colonne, ma non è necessario in quanto saranno colonne con dtype objecto categorical(più sotto).

In [2]: df_encoded = pd.get_dummies(df, columns=['a','b', 'c'], drop_first=True)
        print(df_encoded]
Out[2]:
          d  a_Var2  a_Var3  b_Var2  b_Var3  c_Var2  c_Var3
0  0.953153       0       1       0       1       0       1
1  0.924896       0       0       1       0       0       0
2  0.273205       1       0       1       0       1       0
3  0.459676       1       0       0       0       0       1
4  0.114358       1       0       0       0       0       0

Nella tua specifica applicazione, dovrai fornire un elenco di colonne che sono categoriche o dovrai dedurre quali colonne sono categoriali.

Nel migliore dei casi il tuo frame di dati ha già queste colonne con un dtype=categorye puoi passare columns=df.columns[df.dtypes == 'category']a get_dummies.

Altrimenti, ti suggerisco di impostare dtypetutte le altre colonne come appropriato (suggerimento: pd.to_numeric, pd.to_datetime, ecc.) E ti objectrimarranno le colonne che hanno un tipo e queste dovrebbero essere le tue colonne categoriali.

Le colonne del parametro pd.get_dummies sono predefinite come segue:

columns : list-like, default None
    Column names in the DataFrame to be encoded.
    If `columns` is None then all the columns with
    `object` or `category` dtype will be converted.

2

Per convertire tipi di più colonne contemporaneamente userei qualcosa del genere:

df2 = df.select_dtypes(include = ['type_of_insterest'])

df2[df2.columns].apply(lambda x:x.astype('category'))

Quindi vorrei unirmi a loro original df.


Penso che df2[df2.columns] = df2[df2.columns].astype('category')faccia lo stesso, no apply, no lambda.
paulperry
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.