2016-05-25 2 views
15

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

вы ищете ' sklearn.OneHotEncoder'. Посмотрите здесь: http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html – ssm

+0

@ssm: 'get_dummies' реализует те же функции, что и« OneHotEncoder », с дополнительным преимуществом, что выход легко понять базу данных pandas с помеченными столбцами вместо простой «ndarray». –

+0

Я неправильно понял вопрос. Благодаря! – ssm

ответ

15

Использование транспонировать и переиндексации

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 
+0

Ясный и лаконичный, спасибо! – Berne

+0

, используя ключевое слово 'reindex'' column' (т. Е. 'Dummies.reindex (columns = cats)'), вам не нужно выполнять двойную транспозицию. –

+0

Также 'reindex' имеет параметр' fill_value', который делает то, что вы сделали с помощью 'fillna'. Таким образом, строка перед печатью результата может быть выполнена с помощью: 'dummies = dummies.reindex (columns = cats, fill_value = 0)'. –

2

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

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

+0

Да, это альтернатива, о которой я думал, но я надеялся, что может быть что-то уже реализовано, что было бы проще использовать (не обязательно с 'get_dummies', но единственной альтернативой, которую я нашел, была' sklearn' ' OneHotEncoder', который, похоже, не очень помогает ...) – Berne

+0

Вы можете просто пропустить 'get_dummies' и просто создать все столбцы' 0'-'1' самостоятельно, исходя из самого столбца категории. Думаю, это зависит от размера вашей проблемы. – Stefan

4

Попробуйте это:

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 
+0

'column = cats' в' get_dummies' здесь на самом деле ничего не делает. Опция 'columns' предназначена для выбора подмножества исходного фрейма данных, которое вы хотите закодировать с помощью фиктивных переменных. Кажется, он игнорирует его, если запрашиваемые столбцы не отображаются в фрейме данных. Похоже, что это должно привести к ошибке, но это не –

23

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

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

In [1]: import pandas as pd 

In [2]: cat=pd.Series(list('aba'),index=range(1,4)) 

In [3]: cat=cat.astype('category',categories=list('abc')) 

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

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

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

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

EDIT:

я не следил за точное управление версиями, но был bug в том, как панды не обрабатывает разреженные матрицы, по крайней мере, до версии 0.17.0. Он был скорректирован по версии 0.18.1.

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

+0

Ничего, я не знал об этом типе данных в Pandas, спасибо! – Berne

+4

@ Berne Я знаю, что это может быть немного невежливо, но ... Я думаю, что мой ответ отвечает на ваш вопрос лучше, чем в настоящее время принятый. Любой шанс, что вы могли бы изменить мой на принятый ответ? –

+0

Ну, ну, я выбрал ответ piRSquared, потому что он был ясен, краток и адаптирован к коду, который у меня уже был. Кроме того, именно это я и использовал в том, что я делал, поэтому в какой-то мере это решало мою проблему. Твой был более * информативным * в целом, предоставлен, но это не тот, который я в конечном счете использовал, поэтому я не изменил его на твою, извините ... Я бы дал ему бонусные баллы, если бы мог. – Berne

0

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

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

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

Смежные вопросы