Массовое преобразование категориальных столбцов в Pandas (не одноразовое кодирование)

12

У меня есть панды dataframe с тоннами категоричных колонн, которые я планирую использовать в дерево решений с scikit учиться. Мне нужно преобразовать их в числовые значения (не один горячий вектор). Я могу сделать это с LabelEncoder из scikit учиться. Проблема в том, что их слишком много, и я не хочу конвертировать их вручную.

Что бы быть простой способ автоматизировать этот процесс.

user1700890
источник
Функция get_dummies в пандах может вам помочь. Проверьте документацию здесь для более подробной информации . Я думаю, что он идеально подходит для этого варианта использования, и вы можете дополнительно настроить поведение, предоставляя собственные префиксы.
hssay 19.09.16

Ответы:

11

Если ваши категориальные столбцы в настоящее время являются символами / объектами, вы можете использовать что-то вроде этого, чтобы сделать каждый:

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

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

Если вам нужно вернуться к категориям, я бы создал словарь для сохранения кодировки; что-то типа:

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

Использование mcve Жюльена выведет:

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
источник
Ваш код для поиска objectстолбцов очень полезен.
Джавадба
6

Во-первых, давайте создадим mcve для игры:

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

Теперь мы можем использовать pd.get_dummies для кодирования первых трех столбцов.

Обратите внимание, что я использую drop_firstпараметр, потому что N-1пустышки достаточно для полного описания Nвозможностей (например: если a_Var2и a_Var30, то это a_Var1). Кроме того , я специально указав столбцы , но я не должен , как это будет столбцы с DTYPE либо objectили categorical(подробнее ниже).

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

В вашем конкретном приложении вы должны будете предоставить список столбцов, которые являются Категориальными, или вы должны будете определить, какие столбцы являются Категориальными.

В лучшем случае в вашем фрейме данных эти столбцы уже есть, dtype=categoryи вы можете перейти columns=df.columns[df.dtypes == 'category']к ним get_dummies.

В противном случае я предлагаю установить dtypeвсе остальные столбцы соответствующим образом (подсказка: pd.to_numeric, pd.to_datetime и т. Д.), И у вас останутся столбцы, имеющие objectтип d, и они должны быть вашими категориальными столбцами.

По умолчанию столбцы параметров pd.get_dummies:

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

Чтобы преобразовать типы нескольких столбцов одновременно, я бы использовал что-то вроде этого:

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

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

Тогда я бы присоединился к ним original df.

кибер-математика
источник
Я думаю, df2[df2.columns] = df2[df2.columns].astype('category')делает то же самое, нет apply, нет lambda.
Пол