熊猫将一列列表转换为虚拟对象

新手上路,请多包涵

我有一个数据框,其中一列是我的每个用户所属的组列表。就像是:

 index groups
0     ['a','b','c']
1     ['c']
2     ['b','c','e']
3     ['a','c']
4     ['b','e']

我想做的是创建一系列虚拟列来识别每个用户属于哪些组以便运行一些分析

index  a   b   c   d   e
0      1   1   1   0   0
1      0   0   1   0   0
2      0   1   1   0   1
3      1   0   1   0   0
4      0   1   0   0   0

pd.get_dummies(df['groups'])

不会工作,因为它只会为我的专栏中的每个不同列表返回一列。

该解决方案需要高效,因为数据框将包含 500,000 多行。

原文由 user2900369 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 373
2 个回答

使用 s 为您的 df['groups']

 In [21]: s = pd.Series({0: ['a', 'b', 'c'], 1:['c'], 2: ['b', 'c', 'e'], 3: ['a', 'c'], 4: ['b', 'e'] })

In [22]: s
Out[22]:
0    [a, b, c]
1          [c]
2    [b, c, e]
3       [a, c]
4       [b, e]
dtype: object

这是一个可能的解决方案:

 In [23]: pd.get_dummies(s.apply(pd.Series).stack()).sum(level=0)
Out[23]:
   a  b  c  e
0  1  1  1  0
1  0  0  1  0
2  0  1  1  1
3  1  0  1  0
4  0  1  0  1

这样做的逻辑是:

  • .apply(Series) 将一系列列表转换为数据框
  • .stack() 再次将所有内容放在一列中(创建多级索引)
  • pd.get_dummies( ) 创建假人
  • .sum(level=0 )用于重新合并应该是一行的不同行(通过总结第二级,只保留原始级别( level=0 ))

一个轻微的等价物是 pd.get_dummies(s.apply(pd.Series), prefix='', prefix_sep='').sum(level=0, axis=1)

我不知道这是否足够有效,但无论如何,如果性能很重要,那么将列表存储在数据框中并不是一个好主意。

原文由 joris 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您有大型数据框,则非常快速的解决方案

使用 sklearn.preprocessing.MultiLabelBinarizer

 import pandas as pd
from sklearn.preprocessing import MultiLabelBinarizer

df = pd.DataFrame(
    {'groups':
        [['a','b','c'],
        ['c'],
        ['b','c','e'],
        ['a','c'],
        ['b','e']]
    }, columns=['groups'])

s = df['groups']

mlb = MultiLabelBinarizer()

pd.DataFrame(mlb.fit_transform(s),columns=mlb.classes_, index=df.index)

结果:

     a   b   c   e
0   1   1   1   0
1   0   0   1   0
2   0   1   1   1
3   1   0   1   0
4   0   1   0   1

为我工作,也被建议 在这里这里

原文由 Teoretic 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题