Convertir des données catégoriques dans le cadre de données pandas

102

J'ai un dataframe avec ce type de données (trop de colonnes):

col1        int64
col2        int64
col3        category
col4        category
col5        category

Les colonnes ressemblent à ceci:

Name: col3, dtype: category
Categories (8, object): [B, C, E, G, H, N, S, W]

Je veux convertir toutes les valeurs des colonnes en nombre entier comme ceci:

[1, 2, 3, 4, 5, 6, 7, 8]

J'ai résolu ceci pour une colonne par ceci:

dataframe['c'] = pandas.Categorical.from_array(dataframe.col3).codes

Maintenant, j'ai deux colonnes dans mon dataframe - ancienne col3et nouvelle cet j'ai besoin de supprimer les anciennes colonnes.

C'est une mauvaise pratique. C'est du travail mais dans mon dataframe de nombreuses colonnes et je ne veux pas le faire manuellement.

Comment ça pythonique et juste intelligemment?

Gilaztdinov Rustam
la source

Réponses:

164

Tout d' abord, pour convertir une colonne catégorielles à ses codes numériques, vous pouvez le faire plus facile avec: dataframe['c'].cat.codes.
En outre, il est possible de sélectionner automatiquement toutes les colonnes avec un certain dtype dans un dataframe en utilisant select_dtypes. De cette façon, vous pouvez appliquer l'opération ci-dessus sur plusieurs colonnes sélectionnées automatiquement.

Commencez par créer un exemple de dataframe:

In [75]: df = pd.DataFrame({'col1':[1,2,3,4,5], 'col2':list('abcab'),  'col3':list('ababb')})

In [76]: df['col2'] = df['col2'].astype('category')

In [77]: df['col3'] = df['col3'].astype('category')

In [78]: df.dtypes
Out[78]:
col1       int64
col2    category
col3    category
dtype: object

Ensuite, en utilisant select_dtypespour sélectionner les colonnes, puis en appliquant .cat.codessur chacune de ces colonnes, vous pouvez obtenir le résultat suivant:

In [80]: cat_columns = df.select_dtypes(['category']).columns

In [81]: cat_columns
Out[81]: Index([u'col2', u'col3'], dtype='object')

In [83]: df[cat_columns] = df[cat_columns].apply(lambda x: x.cat.codes)

In [84]: df
Out[84]:
   col1  col2  col3
0     1     0     0
1     2     1     1
2     3     2     0
3     4     0     1
4     5     1     1
joris
la source
14
existe-t-il un moyen facile d'obtenir un mappage entre le code de catégorie et les valeurs de chaîne de catégorie?
Allan Ruin
5
Vous pouvez utiliser: df['col2'].cat.categoriespar exemple.
ogrisel
13
Soulignant à tous ceux qui sont préoccupés que cela NaN-1
mappera
2
Love the 2 liners;)
Jose A
Attention, si le catégoriel est ordonné (un ordinal), les codes numériques renvoyés par cat.codespeuvent ne PAS être ceux que vous voyez dans la série!
paulperry
27

Cela fonctionne pour moi:

pandas.factorize( ['B', 'C', 'D', 'B'] )[0]

Production:

[0, 1, 2, 0]
Scottlittle
la source
20

Si votre préoccupation était uniquement de créer une colonne supplémentaire et de la supprimer plus tard, utilisez simplement une nouvelle colonne en premier lieu.

dataframe = pd.DataFrame({'col1':[1,2,3,4,5], 'col2':list('abcab'),  'col3':list('ababb')})
dataframe.col3 = pd.Categorical.from_array(dataframe.col3).codes

Vous avez terminé. Désormais Categorical.from_arrayobsolète, utilisez Categoricaldirectement

dataframe.col3 = pd.Categorical(dataframe.col3).codes

Si vous avez également besoin du mappage d'index en étiquette, il existe un moyen encore meilleur pour le même

dataframe.col3, mapping_index = pd.Series(dataframe.col3).factorize()

vérifier ci-dessous

print(dataframe)
print(mapping_index.get_loc("c"))
Abhishek
la source
11

Ici, plusieurs colonnes doivent être converties. Donc, une approche que j'ai utilisée est ..

for col_name in df.columns:
    if(df[col_name].dtype == 'object'):
        df[col_name]= df[col_name].astype('category')
        df[col_name] = df[col_name].cat.codes

Cela convertit toutes les colonnes de type chaîne / objet en catégorielles. Applique ensuite les codes à chaque type de catégorie.

shantanu pathak
la source
3

Pour convertir des données catégorielles dans la colonne C des données de l'ensemble de données , nous devons procéder comme suit:

from sklearn.preprocessing import LabelEncoder 
labelencoder= LabelEncoder() #initializing an object of class LabelEncoder
data['C'] = labelencoder.fit_transform(data['C']) #fitting and transforming the desired categorical column.
Fatemeh Asgarinejad
la source
2

Ce que je fais, c'est que je replacevalorise.

Comme ça-

df['col'].replace(to_replace=['category_1', 'category_2', 'category_3'], value=[1, 2, 3], inplace=True)

De cette manière, si la colcolonne a des valeurs catégorielles, elles sont remplacées par les valeurs numériques.

vérité
la source
1

@ Quickbeam2k1, voir ci-dessous -

dataset=pd.read_csv('Data2.csv')
np.set_printoptions(threshold=np.nan)
X = dataset.iloc[:,:].values

Utiliser sklearn entrez la description de l'image ici

from sklearn.preprocessing import LabelEncoder
labelencoder_X=LabelEncoder()
X[:,0] = labelencoder_X.fit_transform(X[:,0])
Prohadoopien
la source
3
Pourquoi n'avez-vous pas simplement corrigé votre réponse précédente? Étonnamment, vous utilisez fit_transformmaintenant à la place transform_fitet corrigé la définition de labelencoder. Pourquoi utilisez-vous iloc[:,:]? c'est inutile. Quelle est la raison derrière l'image? Au cas où vous voudriez me prouver et que @theGtknerd aurait échoué.
Quickbeam2k1
0

Pour une certaine colonne, si vous ne vous souciez pas de la commande, utilisez ceci

df['col1_num'] = df['col1'].apply(lambda x: np.where(df['col1'].unique()==x)[0][0])

Si vous vous souciez de la commande, spécifiez-les sous forme de liste et utilisez-la

df['col1_num'] = df['col1'].apply(lambda x: ['first', 'second', 'third'].index(x))
SaTa
la source