在 pandas for python 中创建虚拟变量

Posted

技术标签:

【中文标题】在 pandas for python 中创建虚拟变量【英文标题】:Creating dummy variables in pandas for python 【发布时间】:2012-07-20 05:28:16 【问题描述】:

我正在尝试使用 python 中的 pandas 从分类变量创建一系列虚拟变量。我遇到了get_dummies 函数,但每当我尝试调用它时,我都会收到一个错误,即名称未定义。

任何创建虚拟变量的想法或其他方法将不胜感激。

编辑:由于其他人似乎遇到了这个问题,pandas 中的get_dummies 函数现在可以正常工作了。这意味着以下应该可以工作:

import pandas as pd

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

更多信息请参见http://blog.yhathq.com/posts/logistic-regression-and-python.html

【问题讨论】:

【参考方案1】:

当我想到虚拟变量时,我会想到在 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()

【讨论】:

考虑虚拟陷阱!很好。删除一个虚拟变量列很容易,但您会认为 get_dummies 会将此作为选项。 我认为这应该是最好的答案。它只缺少一件事import statsmodels.api as sm.. 这样任何人都可以在她/他的 Ipython 笔记本上试用它 @stackunderflow,已修复。谢谢。 更新:pandas 版本 0.18.0,get_dummies 现在有一个 drop_first 参数,如果设置为 True 将删除第一个虚拟变量。例如:pd.get_dummies(df['dummy'], drop_first=True) get_dummies 有一个 drop_first 选项。【参考方案2】:

很难从这个问题中推断出你在寻找什么,但我的最佳猜测如下。

如果我们假设您有一个 DataFrame,其中某列是“类别”并且包含类别的整数(或其他唯一标识符),那么我们可以执行以下操作。

调用 DataFrame dfrm,并假设对于每一行,dfrm['Category'] 是从 1 到 N 的整数集合中的某个值。那么,

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

现在每个类别都会有一个新的指标列,根据该行中的数据是否属于该类别,该列是真/假。

如果你想控制类别名称,你可以制作一个字典,例如

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

产生具有指定名称的列,而不仅仅是类别值的字符串转换。事实上,对于某些类型,str() 可能不会产生任何对您有用的东西。

【讨论】:

现在有没有更好的方法来进行单热编码,指定返回的虚拟变量列的名称?【参考方案3】:

基于official documentation:

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 博客中还有一个不错的 post。

【讨论】:

因为你在最后一行做了 inplace=True ,你返回 none 并最终得到一个空的数据框。我会更新最后一行: df = df.drop(['Category'], axis=1)【参考方案4】:

以下代码返回数据框,其中“类别”列替换为分类列:

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

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

【讨论】:

【参考方案5】:

就我而言,patsy 中的dmatrices 解决了我的问题。实际上,这个函数是为从给定的 DataFrame 中生成因变量和自变量而设计的,它带有 R 样式的公式字符串。但它可以用于从分类特征生成虚拟特征。您需要做的就是删除由dmatrices 自动生成的“拦截”列,而不管您的原始数据帧如何。

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

【讨论】:

【参考方案6】:

您可以创建虚拟变量来处理分类数据

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

这将删除 trainDf 中的原始列,并在 trainDfDummies 数据框的末尾附加带有虚拟变量的列。

它通过在原始列名的末尾附加值来自动创建列名。

【讨论】:

【参考方案7】:

一个非常简单的方法不使用 get_dummies,如果你有非常少的分类变量使用 NumPy 和 Pandas。

让,我有一个名为 的列,它有 3 个分类变量 、 和 ,我们想分别分配 0 和 1。

我们可以用下面的简单代码做到这一点。

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)
 

在上面我们创建了三个新列来存储值“NewYork_State”、“California_State”、“Florida_State”。

Drop the original column

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

【讨论】:

【参考方案8】:

所以我今天(2013 年 7 月 25 日)实际上需要这个问题的答案,所以我早些时候写了这个。我已经用一些玩具示例对其进行了测试,希望你能从中获得一些好处

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

【讨论】:

我编辑了原始问题以反映最新版本的熊猫。 get_dummies 函数现在可以正常工作了。【参考方案9】:

我使用这段代码为每个状态创建了一个虚拟变量。

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() 的见解)

【讨论】:

【参考方案10】:

处理分类特征 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`

【讨论】:

【参考方案11】:

一种基于具有类别值的列创建虚拟变量的简单而可靠的方法:

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

但在进行一些 OLS 回归时要小心,因为您需要排除其中一个类别,以免陷入虚拟陷阱变量

【讨论】:

以上是关于在 pandas for python 中创建虚拟变量的主要内容,如果未能解决你的问题,请参考以下文章

python 在Pandas中创建DataFrame的不同方法

如果以后在 python (pandas) 中出现相同的值,则为虚拟

根据其他列值/ Pandas -Python 在数据框中创建 ID 列

在 python 中创建一个函数,它将在 pandas 数据框中估算均值或中值

如何从带有额外分隔符的 csv 在 python 中创建 pandas 数据框?

如何在 Python 中创建具有两列作为元组或 Pandas 数据框的单个变量?