Conversion de masse des colonnes catégorielles dans Pandas (pas d'encodage à chaud)


12

J'ai une base de données pandas avec des tonnes de colonnes catégorielles, que je prévois d'utiliser dans l'arbre de décision avec scikit-learn. J'ai besoin de les convertir en valeurs numériques (pas un seul vecteur chaud). Je peux le faire avec LabelEncoder de scikit-learn. Le problème est qu'il y en a trop et je ne veux pas les convertir manuellement.

Quel serait un moyen facile d'automatiser ce processus.


La fonction get_dummies dans les pandas peut vous aider. Consultez la documentation ici pour plus de détails . Je pense que cela couvre parfaitement ce cas d'utilisation et vous pouvez modifier davantage le comportement en fournissant des préfixes personnalisés.
hssay

Réponses:


11

Si vos colonnes catégorielles sont actuellement des caractères / objets, vous pouvez utiliser quelque chose comme ceci pour faire chacune:

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

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

Si vous avez besoin de pouvoir revenir aux catégories, je créerais un dictionnaire pour enregistrer l'encodage; quelque chose comme:

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

L'utilisation de la mcve de Julien produira:

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')}

Votre code pour trouver les objectcolonnes est très utile.
javadba

6

Tout d'abord, créons un mcve pour jouer avec:

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

Nous pouvons maintenant utiliser pd.get_dummies pour encoder les trois premières colonnes.

Notez que j'utilise le drop_firstparamètre parce que les N-1variables muettes sont suffisantes pour décrire complètement les Npossibilités (par exemple: si a_Var2et a_Var3sont 0, alors c'est a_Var1). De plus, je spécifie spécifiquement les colonnes mais je n'ai pas à le faire car ce seront des colonnes avec dtype objectou categorical(plus ci-dessous).

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

Dans votre application spécifique, vous devrez fournir une liste de colonnes catégorielles ou vous devrez déduire quelles colonnes sont catégoriques.

Dans le meilleur des cas, votre trame de données a déjà ces colonnes avec un dtype=categoryet vous pouvez passer columns=df.columns[df.dtypes == 'category']à get_dummies.

Sinon, je suggère de définir la dtypede toutes les autres colonnes comme approprié (indice: pd.to_numeric, pd.to_datetime, etc.) et vous vous retrouverez avec des colonnes qui ont un objectdtype et celles-ci devraient être vos colonnes catégorielles.

La valeur par défaut des colonnes de paramètres pd.get_dummies est la suivante:

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

Afin de convertir des types de plusieurs colonnes à la fois, j'utiliserais quelque chose comme ceci:

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

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

Je les rejoindrais ensuite original df.


Je pense df2[df2.columns] = df2[df2.columns].astype('category')que c'est la même chose, non apply, non lambda.
paulperry
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.