Фиктивные переменные, если присутствуют не все категории
У меня есть набор данных, где один из столбцов содержит категориальную переменную. Я хотел бы преобразовать его в несколько фиктивных переменных, и в этом случае я обычно использовал бы 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"])