繁体   English   中英

从熊猫中具有多个值的列中创建假人

[英]Create dummies from column with multiple values in pandas

我正在寻找一种处理以下问题的Python方法。

pandas.get_dummies()方法非常适合从数据pandas.get_dummies()的分类列创建虚拟对象。 例如,如果该列具有['A', 'B'] ,则get_dummies()创建2个虚拟变量,并相应地分配0或1。

现在,我需要处理这种情况。 单个列(称为“标签”)具有类似['A', 'B', 'C', 'D', 'A*C', 'C*D'] get_dummies()创建6个虚拟变量,但我只希望其中4个虚拟变量,以便一行可以有多个1。

有没有办法以pythonic的方式处理这个问题? 我只能想到一些逐步的算法来获取它,但是其中不包括get_dummies()。 谢谢

编辑,希望更清楚!

我知道问这个问题已经有一段时间了,但是(至少现在有) 文档支持的单行代码:

In [4]: df
Out[4]:
      label
0  (a, c, e)
1     (a, d)
2       (b,)
3     (d, e)

In [5]: df['label'].str.join(sep='*').str.get_dummies(sep='*')
Out[5]:
   a  b  c  d  e
0  1  0  1  0  1
1  1  0  0  1  0
2  0  1  0  0  0
3  0  0  0  1  1

我有一个比较干净的解决方案。 假设我们要转换以下数据框

   pageid category
0       0        a
1       0        b
2       1        a
3       1        c

进入

        a  b  c
pageid         
0       1  1  0
1       1  0  1

一种方法是利用scikit-learn的DictVectorizer。 但是,我会对学习其他方法感兴趣。

df = pd.DataFrame(dict(pageid=[0, 0, 1, 1], category=['a', 'b', 'a', 'c']))

grouped = df.groupby('pageid').category.apply(lambda lst: tuple((k, 1) for k in lst))
category_dicts = [dict(tuples) for tuples in grouped]
v = sklearn.feature_extraction.DictVectorizer(sparse=False)
X = v.fit_transform(category_dicts)

pd.DataFrame(X, columns=v.get_feature_names(), index=grouped.index)

您可以使用原始数据生成假人数据帧,隔离包含给定原子的列,然后将结果匹配存储回atom列。

df
Out[28]: 
  label
0     A
1     B
2     C
3     D
4   A*C
5   C*D

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

atom_col = [c for c in dummies.columns if '*' not in c]

for col in atom_col:
    ...:     df[col] = dummies[[c for c in dummies.columns if col in c]].sum(axis=1)
    ...:     

df
Out[32]: 
  label  A  B  C  D
0     A  1  0  0  0
1     B  0  1  0  0
2     C  0  0  1  0
3     D  0  0  0  1
4   A*C  1  0  1  0
5   C*D  0  0  1  1

在遇到sklearn的MultiLabelBinarizer之后,我相信这个问题需要更新的答案。

用法很简单...

# Instantiate the binarizer
mlb = MultiLabelBinarizer()

# Using OP's original data frame
df = pd.DataFrame(data=['A', 'B', 'C', 'D', 'A*C', 'C*D'], columns=["label"])

print(df)
  label
0     A
1     B
2     C
3     D
4   A*C
5   C*D

# Convert to a list of labels
df = df.apply(lambda x: x["label"].split("*"), axis=1)

print(df)
0       [A]
1       [B]
2       [C]
3       [D]
4    [A, C]
5    [C, D]
dtype: object

# Transform to a binary array
array_out = mlb.fit_transform(df)

print(array_out)
[[1 0 0 0]
 [0 1 0 0]
 [0 0 1 0]
 [0 0 0 1]
 [1 0 1 0]
 [0 0 1 1]]

# Convert back to a dataframe (unnecessary step in many cases)
df_out = pd.DataFrame(data=array_out, columns=mlb.classes_)

print(df_out)
   A  B  C  D
0  1  0  0  0
1  0  1  0  0
2  0  0  1  0
3  0  0  0  1
4  1  0  1  0
5  0  0  1  1

这也非常快,在1000行和50K类中几乎没有时间(.03秒)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM