Фиктивные переменные, если присутствуют не все категории

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

Что происходит, так это то, что get_dummies просматривает данные, доступные в каждом кадре данных, чтобы узнать, сколько их есть, и тем самым создать соответствующее количество фиктивных переменных. Тем не менее, в проблеме, над которой я сейчас работаю, я действительно заранее знаю, что такое возможные категории. Но при просмотре каждого кадра данных индивидуально, не все категории обязательно появляются.

Мой вопрос: есть ли способ передать get_dummies (или эквивалентную функцию) имена категорий, так что для категорий, которые не отображаются в данном фрейме данных, это просто создаст столбец 0s?

Что-то, что сделало бы это:

categories = ['a', 'b', 'c']

   cat
1   a
2   b
3   a

Станьте этим:

  cat_a  cat_b  cat_c
1   1      0      0
2   0      1      0
3   1      0      0

Ответы

Ответ 1

Использование транспонирования и reindex

import pandas as pd

cats = ['a', 'b', 'c']
df = pd.DataFrame({'cat': ['a', 'b', 'a']})

dummies = pd.get_dummies(df, prefix='', prefix_sep='')
dummies = dummies.T.reindex(cats).T.fillna(0)

print dummies

    a    b    c
0  1.0  0.0  0.0
1  0.0  1.0  0.0
2  1.0  0.0  0.0

Ответ 2

Есть ли способ передать в get_dummies (или эквивалентную функцию) имена категорий, чтобы для категорий, которые не появляются в данном кадре данных, он просто создал столбец 0?

Да, есть! У Pandas есть специальный тип Series только для категориальных данных. Одним из атрибутов этой серии являются возможные категории, которые get_dummies учитывает. Вот пример:

In [1]: import pandas as pd

In [2]: possible_categories = list('abc')

In [3]: cat = pd.Series(list('aba'))

In [4]: cat = cat.astype('category', categories=possible_categories)

In [5]: cat
Out[5]: 
0    a
1    b
2    a
dtype: category
Categories (3, object): [a, b, c]

Тогда get_dummies будет делать именно то, что вы хотите!

In [6]: pd.get_dummies(cat)
Out[6]: 
   a  b  c
0  1  0  0
1  0  1  0
2  1  0  0

Существует множество других способов создания категориальных Series или DataFrame, и это наиболее удобный для меня DataFrame. Вы можете прочитать обо всех них в документации для панд.

РЕДАКТИРОВАТЬ:

Я не следил за точным управлением версиями, но была ошибка в том, как pandas обрабатывает разреженные матрицы, по крайней мере до версии 0.17.0. Исправлено в версии 0.18.1 (выпущена в мае 2016 года).

Для версии 0.17.0, если вы попытаетесь сделать это с опцией sparse=True с DataFrame, столбец нулей для отсутствующей фиктивной переменной будет столбцом NaN, и он будет преобразован в плотный.

Ответ 3

Попробуйте следующее:

In[1]: import pandas as pd
       cats = ["a", "b", "c"]

In[2]: df = pd.DataFrame({"cat": ["a", "b", "a"]})

In[3]: pd.concat((pd.get_dummies(df.cat, columns=cats), pd.DataFrame(columns=cats))).fillna(0)
Out[3]: 
     a    b    c
0  1.0  0.0  0
1  0.0  1.0  0
2  1.0  0.0  0

Ответ 4

Я не думаю, что get_dummies предоставляет это из коробки, он позволяет только создать дополнительный column, который выделяет значения NaN.

Чтобы добавить отсутствующий columns самостоятельно, вы можете использовать pd.concat вдоль axis=0 для вертикального "стека" DataFrames (фиктивные столбцы плюс DataFrame id) и автоматически создавать любые отсутствующие столбцы, используйте fillna(0) для замены отсутствующих значений, а затем используйте .groupby('id'), чтобы снова разделить различные DataFrame.

Ответ 5

Добавление отсутствующей категории в тестовый набор:

# Get missing columns in the training test
missing_cols = set( train.columns ) - set( test.columns )
# Add a missing column in test set with default value equal to 0
for c in missing_cols:
    test[c] = 0
# Ensure the order of column in the test set is in the same order than in train set
test = test[train.columns]

Обратите внимание, что этот код также удаляет столбец из категории в тестовом наборе данных, но не присутствует в наборе учебных материалов

Ответ 6

Я спрашивал об этом на пандах гитхуб. Оказывается, это действительно легко обойти, когда вы определяете столбец как Categorical где вы определяете все возможные категории.

df['col'] = pd.Categorical(df['col'], categories=['a', 'b', 'c', 'd'])

get_dummies() сделает все остальное, как и ожидалось.

Ответ 7

Как подсказывают другие - Преобразование ваших категорийных функций в тип данных "категория" должно решить проблему невидимой метки с помощью "get_dummies".

# Your Data frame(df)
from sklearn.model_selection import train_test_split
X = df.loc[:,df.columns !='label']
Y = df.loc[:,df.columns =='label']

# Split the data into 70% training and 30% test
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3) 

# Convert Categorical Columns in your data frame to type 'category'
for col in df.select_dtypes(include=[np.object]).columns:
    X_train[col] = X_train[col].astype('category', categories = df[col].unique())
    X_test[col] = X_test[col].astype('category', categories = df[col].unique())

# Now, use get_dummies on training, test data and we will get same set of columns
X_train = pd.get_dummies(X_train,columns = ["Categorical_Columns"])
X_test = pd.get_dummies(X_test,columns = ["Categorical_Columns"])