Создание фиктивных переменных в пандах для python

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

Любые мысли или другие способы создания фиктивных переменных будут оценены.

РЕДАКТИРОВАТЬ: так как другие, кажется, сталкиваются с этим, get_dummies Функция в пандах теперь отлично работает. Это означает, что должно работать следующее:

import pandas as pd

dummies = pd.get_dummies(df['Category'])

См. http://blog.yhathq.com/posts/logistic-regression-and-python.html для получения дополнительной информации.

12 ответов

Решение

Трудно понять, что вы ищете по этому вопросу, но мое лучшее предположение следующее.

Если мы предположим, что у вас есть DataFrame, где некоторый столбец имеет значение "Category" и содержит целые числа (или иные уникальные идентификаторы) для категорий, то мы можем сделать следующее.

Вызовите DataFrame dfrmи предположим, что для каждого ряда dfrm['Category'] какое-то значение в множестве целых чисел от 1 до N. Тогда

for elem in dfrm['Category'].unique():
    dfrm[str(elem)] = dfrm['Category'] == elem

Теперь для каждой категории будет новый столбец индикатора, который будет True/False в зависимости от того, находятся ли данные в этой строке в этой категории.

Если вы хотите контролировать имена категорий, вы можете сделать словарь, такой как

cat_names = {1:'Some_Treatment', 2:'Full_Treatment', 3:'Control'}
for elem in dfrm['Category'].unique():
    dfrm[cat_names[elem]] = dfrm['Category'] == elem

чтобы получить столбцы с указанными именами, а не просто строковое преобразование значений категории. На самом деле, для некоторых типов, str() может не дать ничего полезного для вас.

Когда я думаю о фиктивных переменных, я думаю об их использовании в контексте регрессии OLS, и я бы сделал что-то вроде этого:

import numpy as np
import pandas as pd
import statsmodels.api as sm

my_data = np.array([[5, 'a', 1],
                    [3, 'b', 3],
                    [1, 'b', 2],
                    [3, 'a', 1],
                    [4, 'b', 2],
                    [7, 'c', 1],
                    [7, 'c', 1]])                


df = pd.DataFrame(data=my_data, columns=['y', 'dummy', 'x'])
just_dummies = pd.get_dummies(df['dummy'])

step_1 = pd.concat([df, just_dummies], axis=1)      
step_1.drop(['dummy', 'c'], inplace=True, axis=1)
# to run the regression we want to get rid of the strings 'a', 'b', 'c' (obviously)
# and we want to get rid of one dummy variable to avoid the dummy variable trap
# arbitrarily chose "c", coefficients on "a" an "b" would show effect of "a" and "b"
# relative to "c"
step_1 = step_1.applymap(np.int) 

result = sm.OLS(step_1['y'], sm.add_constant(step_1[['x', 'a', 'b']])).fit()
print result.summary()

На основании официальной документации:

dummies = pd.get_dummies(df['Category']).rename(columns=lambda x: 'Category_' + str(x))
df = pd.concat([df, dummies], axis=1)
df = df.drop(['Category'], inplace=True, axis=1)

Также есть хороший пост в блоге FastML.

Следующий код возвращает фрейм данных с заменой столбца "Категория" категориальными столбцами:

df_with_dummies = pd.get_dummies(df, prefix='Category_', columns=['Category'])

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.get_dummies.html

Для моего случая dmatrices в patsy решил мою проблему. Фактически, эта функция предназначена для генерации зависимых и независимых переменных из заданного DataFrame со строкой формулы в R-стиле. Но его можно использовать для генерации фиктивных черт из категориальных черт. Все, что вам нужно сделать, это удалить столбец "Перехват", который генерируется dmatrices автоматически независимо от вашего исходного DataFrame.

import pandas as pd
from patsy import dmatrices

df_original = pd.DataFrame({
   'A': ['red', 'green', 'red', 'green'],
   'B': ['car', 'car', 'truck', 'truck'],
   'C': [10,11,12,13],
   'D': ['alice', 'bob', 'charlie', 'alice']},
   index=[0, 1, 2, 3])

_, df_dummyfied = dmatrices('A ~ A + B + C + D', data=df_original, return_type='dataframe')
df_dummyfied = df_dummyfied.drop('Intercept', axis=1)

df_dummyfied.columns    
Index([u'A[T.red]', u'B[T.truck]', u'D[T.bob]', u'D[T.charlie]', u'C'], dtype='object')

df_dummyfied
   A[T.red]  B[T.truck]  D[T.bob]  D[T.charlie]     C
0       1.0         0.0       0.0           0.0  10.0
1       0.0         0.0       1.0           0.0  11.0
2       1.0         1.0       0.0           1.0  12.0
3       0.0         1.0       0.0           0.0  13.0

Вы можете создать фиктивные переменные для обработки категориальных данных

# Creating dummy variables for categorical datatypes
trainDfDummies = pd.get_dummies(trainDf, columns=['Col1', 'Col2', 'Col3', 'Col4'])

Это приведет к удалению исходных столбцов в trainDf и добавлению столбца с фиктивными переменными в конце фрейма данных trainDfDummies.

Он автоматически создает имена столбцов, добавляя значения в конце исходного имени столбца.

A very simple approach without using get_dummies if you have very less categorical variable using NumPy and Pandas.

let, i have a column named <"State"> and it have 3 categorical variable <'New York'>, <'California'> and <'Florida'> and we want to assign 0 and 1 for respectively.

we can do it with following simple code.

      import numpy as np
import pandas as pd

dataset['NewYork_State'] = np.where(dataset['State']=='New York', 1, 0)
dataset['California_State'] = np.where(dataset['State']=='California', 1, 0)
dataset['Florida_State'] = np.where(dataset['State']=='Florida', 1, 0)
 

Above we create Three New Columns for storing values "NewYork_State", "California_State", "Florida_State".

Drop the original column

      dataset.drop(columns=['State'],axis=1,inplace=True)

Так что мне на самом деле нужен был ответ на этот вопрос сегодня (25.07.2013), поэтому я написал это ранее. Я проверил это на нескольких примерах игрушек, надеюсь, вы получите некоторое преимущество

def categorize_dict(x, y=0):
    # x Requires string or numerical input
    # y is a boolean that specifices whether to return category names along with the dict.
    # default is no
    cats = list(set(x))
    n = len(cats)
    m = len(x)
    outs = {}
    for i in cats:
        outs[i] = [0]*m
    for i in range(len(x)):
        outs[x[i]][i] = 1
    if y:
        return outs,cats
    return outs

Если вы хотите заменить список переменных фиктивными функциями:

      # create an empty list to store the dataframes
   dataframes = []

# iterate over the list of categorical features
 for feature in categoricalFeatures:

   # create a dataframe with dummy variables for the current feature
      df_feature = pd.get_dummies(df_raw[feature])

   # add the dataframe to the list
      dataframes.append(df_feature)`

# concatenate the dataframes to create a single dataframe
  df_dummies = pd.concat(dataframes, axis=1)
  df_final = pd.concat([df_raw, df_dummies], axis=1).drop(columns = 
                                                      categoricalFeatures, axis = 1)

При работе с категориальными функциями scikit-learn ожидает, что все функции будут числовыми. Так, как мы включаем категорическую особенность в нашу модель?

Упорядоченные категории: преобразуйте их в разумные числовые значения (пример: small=1, medium=2, large=3) Неупорядоченные категории: используйте фиктивное кодирование (0/1) Каковы категориальные особенности в нашем наборе данных?

Упорядоченные категории: погода (уже закодированные с разумными числовыми значениями) Неупорядоченные категории: сезон (требуется фиктивная кодировка), праздничные дни (уже фиктивная кодировка), рабочий день (уже фиктивная кодировка) Для сезона мы не можем просто оставить кодировку 1 = весна, 2 = лето, 3 = осень и 4 = зима, потому что это подразумевало бы упорядоченные отношения. Вместо этого мы создаем несколько фиктивных переменных:

# An utility function to create dummy variable
`def create_dummies( df, colname ):
col_dummies = pd.get_dummies(df[colname], prefix=colname)
col_dummies.drop(col_dummies.columns[0], axis=1, inplace=True)
df = pd.concat([df, col_dummies], axis=1)
df.drop( colname, axis = 1, inplace = True )
return df`

Я создал фиктивную переменную для каждого состояния, используя этот код.

def create_dummy_column(series, f):
    return series.apply(f)

for el in df.area_title.unique():
    col_name = el.split()[0] + "_dummy"
    f = lambda x: int(x==el)
    df[col_name] = create_dummy_column(df.area_title, f)
df.head()

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

(Спасибо @prpl.mnky.dshwshr за понимание.unique())

Простой и надежный способ создания макетов на основе столбца со значениями вашей категории:

      for category in list(df['category_column'].unique()):
    df[category] = lis(map(lambda x: 1 if x==category else 0, df['category_column']))

Но будьте осторожны при выполнении некоторой регрессии OLS, потому что вам нужно будет исключить одну из категорий, чтобы не попасться на фиктивную переменную-ловушку.

Другие вопросы по тегам