Columnas categóricas de conversión masiva en pandas (no codificación de una sola vez)

12

Tengo un marco de datos de pandas con toneladas de columnas categóricas, que planeo usar en el árbol de decisiones con scikit-learn. Necesito convertirlos a valores numéricos (no uno vectores calientes). Puedo hacerlo con LabelEncoder de scikit-learn. El problema es que hay demasiados y no quiero convertirlos manualmente.

Cuál sería una manera fácil de automatizar este proceso.

usuario1700890
fuente
La función get_dummies en pandas puede ayudarte. Consulte la documentación aquí para más detalles . Creo que cubre perfectamente este caso de uso y puede modificar aún más el comportamiento al proporcionar prefijos personalizados.
hssay

Respuestas:

11

Si sus columnas categóricas son actualmente caracteres / objetos, puede usar algo como esto para hacer cada una:

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

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

Si necesita volver a las categorías, crearía un diccionario para guardar la codificación; algo como:

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])

El uso de mcve de Julien generará:

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')}
george_w_kush
fuente
Su código para encontrar las objectcolumnas es muy útil.
javadba
6

Primero, creemos un mcve para jugar:

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

Ahora podemos usar pd.get_dummies para codificar las primeras tres columnas.

Tenga en cuenta que estoy usando el drop_firstparámetro porque los N-1dummies son suficientes para describir completamente las Nposibilidades (por ejemplo: si a_Var2y a_Var3son 0, entonces es a_Var1). Además, estoy especificando específicamente las columnas, pero no tengo que hacerlo, ya que serán columnas con dtype objecto categorical(más abajo).

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

En su aplicación específica, deberá proporcionar una lista de columnas que son categóricas, o deberá inferir qué columnas son categóricas.

Mejor de los casos su trama de datos ya tiene estas columnas con una dtype=categoryy se puede pasar columns=df.columns[df.dtypes == 'category']a get_dummies.

De lo contrario, sugiero configurar el dtyperesto de las columnas según corresponda (sugerencia: pd.to_numeric, pd.to_datetime, etc.) y quedará con columnas que tienen un objecttipo y estas deberían ser sus columnas categóricas.

Las columnas del parámetro pd.get_dummies están predeterminadas de la siguiente manera:

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.
Julien Marrec
fuente
2

Para convertir tipos de columnas múltiples a la vez, usaría algo como esto:

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

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

Luego me uniría a ellos original df.

cibermatemáticas
fuente
Creo que df2[df2.columns] = df2[df2.columns].astype('category')hace lo mismo, no apply, no lambda.
paulperry