Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 不是所有类别都存在时的虚拟变量_Python_Pandas_Machine Learning_Dummy Variable - Fatal编程技术网

Python 不是所有类别都存在时的虚拟变量

Python 不是所有类别都存在时的虚拟变量,python,pandas,machine-learning,dummy-variable,Python,Pandas,Machine Learning,Dummy Variable,我有一组数据帧,其中一列包含一个分类变量。我想把它转换成几个虚拟变量,在这种情况下,我通常使用get\u dummies 发生的事情是,get_dummies查看每个数据帧中可用的数据,找出有多少类别,从而创建适当数量的虚拟变量。然而,在我现在研究的问题中,我实际上提前知道了可能的类别。但当单独查看每个数据帧时,并不一定会出现所有类别 我的问题是:有没有一种方法可以传递给get_dummies(或等效函数)类别的名称,以便对于给定数据帧中没有出现的类别,它只创建一列0 这就是: categori

我有一组数据帧,其中一列包含一个分类变量。我想把它转换成几个虚拟变量,在这种情况下,我通常使用
get\u dummies

发生的事情是,
get_dummies
查看每个数据帧中可用的数据,找出有多少类别,从而创建适当数量的虚拟变量。然而,在我现在研究的问题中,我实际上提前知道了可能的类别。但当单独查看每个数据帧时,并不一定会出现所有类别

我的问题是:有没有一种方法可以传递给
get_dummies
(或等效函数)类别的名称,以便对于给定数据帧中没有出现的类别,它只创建一列0

这就是:

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

我不认为
get_dummies
提供了这种开箱即用的功能,它只允许创建一个额外的
,突出显示
NaN

要自己添加缺少的
,您可以使用
pd.concat
沿
axis=0
垂直“堆叠”数据帧(虚拟列加上一个
DataFrame
id
),并自动创建任何缺少的列,使用
fillna(0)
替换缺少的值,然后使用
.groupby('id')
再次分离各种
数据帧。

尝试以下操作:

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

使用转置和重新索引

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

TL;博士

pd.get_dummies(cat.astype(pd.CategoricalDtype(categories=categories)))
  • 老熊猫:
    pd.get\u假人(cat.astype('category',categories=categories))
是否有一种方法可以传递以获取_dummies(或等效函数)类别的名称,以便对于未出现在给定数据帧中的类别,只创建一列0

是的,有!熊猫有一个特殊类型的系列,只为熊猫。本系列的属性之一是可能的类别,
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(pd.CategoricalDtype(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
还有许多其他方法可以创建一个分类的
系列
数据帧
,这正是我觉得最方便的方法。您可以在中阅读所有这些内容

编辑:

我没有遵循确切的版本控制,但至少在版本0.17.0之前,pandas处理稀疏矩阵的方式有一个很大的差异。版本0.18.1(2016年5月发布)对其进行了更正

对于版本0.17.0,如果您尝试使用
DataFrame
sparse=True
选项执行此操作,则缺少的虚拟变量的零列将是
NaN
列,并将其转换为稠密


看起来熊猫0.21.0添加了一个
CategoricalDType
,创建明确包含原始答案中的类别的类别被否决了,我不太确定何时添加测试集中缺少的类别:

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

请注意,此代码还删除了测试数据集中由category产生的列,但不存在于培训数据集中

我在github上问过这个问题。事实证明,当您将列定义为一个
Categorical
,定义所有可能的类别时,很容易绕过它

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

get_dummies()
将按预期完成其余工作。

正如其他人所建议的那样-将分类功能转换为“category”数据类型应该可以使用“get_dummies”解决看不见的标签问题


越短越好:

import pandas as pd

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

pd.get_dummies(df, prefix='', prefix_sep='').reindex(columns = cats, fill_value=0)
结果:

    a   b   c
0   1   0   0
1   0   1   0
2   1   0   0
    cat_a   cat_b   cat_c
0   1         0     0
1   0         1     0
2   1         0     0
    cat_a   cat_b   cat_c
0   1         0     0
1   0         1     0
2   1         0     0
注:

  • cats
    需要成为熊猫索引
  • prefix=''
    prefix\u sep=''
    需要设置才能使用您首先定义的cats类别。否则,
    get_dummie
    将转换为:
    cats_a
    cats_b
    cats_c
    )。对我来说,这是更好的,因为它是明确的
  • 使用fill_值=0从列
    c
    转换
    NaN
    。或者,您可以在句子末尾使用
    fillna(0)
    。(我不知道哪个更快)
以下是一个较短的版本(更改了索引值):

结果:

    a   b   c
0   1   0   0
1   0   1   0
2   1   0   0
    cat_a   cat_b   cat_c
0   1         0     0
1   0         1     0
2   1         0     0
    cat_a   cat_b   cat_c
0   1         0     0
1   0         1     0
2   1         0     0
奖金轨道

我想你有这些分类是因为你以前使用训练数据做了一个虚拟/一个热的。您可以保存原始编码(
.columns
),然后在生产期间应用:

cats = pd.Index(['cat_a', 'cat_b', 'cat_c']) # it might come from the original onehot encoding (df_ohe.columns)

import pickle

with open('cats.pickle', 'wb') as handle:
    pickle.dump(cats, handle, protocol=pickle.HIGHEST_PROTOCOL)


with open('cats.pickle', 'rb') as handle:
    saved_cats = pickle.load(handle)



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

pd.get_dummies(df).reindex(columns = saved_cats, fill_value=0)
结果:

    a   b   c
0   1   0   0
1   0   1   0
2   1   0   0
    cat_a   cat_b   cat_c
0   1         0     0
1   0         1     0
2   1         0     0
    cat_a   cat_b   cat_c
0   1         0     0
1   0         1     0
2   1         0     0

我最近也在寻找解决这个问题的方法,但是使用了多列数据帧和两个数据集(机器学习任务的训练集和测试集)。测试数据帧与列车数据帧具有相同的分类列,但其中一些列缺少列车数据帧中存在的类别

我不想手动为每个列定义所有可能的类别。相反,我将列车和测试数据帧合并为一个称为get_dummies的数据帧,然后将其拆分为两个

# train_cat, test_cat are dataframes instantiated elsewhere

train_test_cat = pd.concat([train_cat, test_cat]
tran_test_cat = pd.get_dummies(train_test_cat, axis=0))

train_cat = train_test_cat.iloc[:train_cat.shape[0], :]
test_cat = train_test_cat.iloc[train_cat.shape[0]:, :]

如果你知道你的类别,你可以按照你的建议首先应用
pd.get_dummies()
,然后添加缺少的类别列

这将创建缺少
cat_c
的示例:

将熊猫作为pd导入
类别=['a','b','c']
df=pd.DataFrame(列表('aba'),列=['cat'])
df=pd.get_假人(df)
打印(df)
猫a猫b
0      1      0
1      0      1
2      1      0
现在,只需使用union操作(如所示)添加缺少的类别列

可能的_类别=['cat_uu'+类别中的猫的猫]
df=df.reindex(df.columns.union(可能的_类别,排序=False),axis=1,fill_值=0)
打印(df)
猫a猫b猫c
0      1      0      0
1      0      1      0
2      1      0      0

是的,这是我考虑过的另一种选择,但是