我有一组数据框,其中一列包含一个分类变量。我想将其转换为几个虚拟变量,在这种情况下,我通常会使用get_dummies
。
get_dummies
会查看每个数据框中可用的数据,以找出有多少类别,从而创建适当数量的虚拟变量。但是,在我现在正在工作的问题中,我实际上事先知道可能的类别是什么。但是,当单独查看每个数据框时,并非所有类别都必须出现。
我的问题是:有没有办法将类别名称传递给get_dummies
(或等效函数),以便对于不会出现在给定数据框中的类别, #39; d只创建一个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
答案 0 :(得分:32)
有没有办法将get_dummies(或等效函数)传递给类别的名称,这样,对于没有出现在给定数据框中的类别,它只是创建一个0的列? / p>
是的,有! Pandas有一种特殊类型的系列仅供categorical data使用。本系列的一个属性是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
,这只是我觉得最方便的方法。您可以在the pandas documentation中了解所有这些内容。
修改强>
我没有遵循确切的版本控制,但是pandas如何处理稀疏矩阵有一个bug,至少在版本0.17.0之前。它由版本0.18.1(2016年5月发布)更正。
对于版本0.17.0,如果您尝试使用带有sparse=True
的{{1}}选项执行此操作,则缺少虚拟变量的零列将是DataFrame
的列,它将被转换为密集。
答案 1 :(得分:23)
使用转置和重新索引
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 :(得分: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
答案 3 :(得分:3)
我不认为get_dummies
提供了开箱即用的功能,它只允许创建一个突出显示column
值的额外NaN
。
要自己添加遗失的columns
,您可以使用pd.concat
axis=0
垂直“堆叠”DataFrames
(虚拟列加DataFrame
id
)并自动创建任何缺失的列,使用fillna(0)
替换缺失的值,然后使用.groupby('id')
再次分隔各种DataFrame
。
答案 4 :(得分:2)
我确实在熊猫github上问过这个问题。事实证明,将列定义为Categorical
并定义所有可能的类别时,绕过它确实很容易。
df['col'] = pd.Categorical(df['col'], categories=['a', 'b', 'c', 'd'])
get_dummies()
将按预期完成剩下的工作。
答案 5 :(得分:1)
在测试集中添加缺少的类别:
# 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 :(得分:1)
根据其他人的建议-将“分类”功能转换为“类别”数据类型应使用“ 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"])
答案 7 :(得分:1)
越短越好:
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
注意:
cats
必须是熊猫索引prefix=''
和prefix_sep=''
才能使用最初定义的cats类别。否则,get_dummies
转换为:cats_a
,cats_b
和cats_c
)。对我来说,这更好,因为它是明确的。 NaN
列中的c
。或者,您可以在句子的末尾使用fillna(0)
。 (我不知道哪一个更快)。这是一个较短-较短的版本(已更改索引值):
import pandas as pd
cats = pd.Index(['cat_a', 'cat_b', 'cat_c'])
df = pd.DataFrame({'cat': ['a', 'b', 'a']})
pd.get_dummies(df).reindex(columns = cats, fill_value=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)
结果:
cat_a cat_b cat_c
0 1 0 0
1 0 1 0
2 1 0 0
答案 8 :(得分:0)
如果您知道自己的类别,则可以按照建议首先应用pd.get_dummies()
,然后再添加缺少的类别列。
这将创建缺少cat_c
的示例:
import pandas as pd
categories = ['a', 'b', 'c']
df = pd.DataFrame(list('aba'), columns=['cat'])
df = pd.get_dummies(df)
print(df)
cat_a cat_b
0 1 0
1 0 1
2 1 0
现在,只需使用联合操作(如suggested here)添加缺少的类别列即可。
possible_categories = ['cat_' + cat for cat in categories]
df = df.reindex(df.columns.union(possible_categories, sort=False), axis=1, fill_value=0)
print(df)
cat_a cat_b cat_c
0 1 0 0
1 0 1 0
2 1 0 0
答案 9 :(得分:-1)
我最近正在寻找解决同一问题的方法,但是使用多列数据框和两个数据集(用于机器学习任务的训练集和测试集)。测试数据框的类别列与火车数据框相同,但是其中一些列缺少火车数据框中存在的类别。
我不想为每列手动定义所有可能的类别。相反,我将训练和测试数据帧合并为一个,称为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]:, :]