Pandas:在列表的每个元素上使用 groupby

Posted

技术标签:

【中文标题】Pandas:在列表的每个元素上使用 groupby【英文标题】:Pandas : Use groupby on each element of list 【发布时间】:2017-06-06 10:05:55 【问题描述】:

也许我错过了显而易见的事情。

我有一个看起来像这样的熊猫数据框:

   id        product              categories
    0        Silmarillion         ['Book', 'Fantasy']
    1        Headphones           ['Electronic', 'Material']
    2        Dune                 ['Book', 'Sci-Fi']

我想使用 groupby 函数来统计类别列中每个元素的出现次数,所以这里的结果是

Book       2
Fantasy    1
Electronic 1
Material   1
Sci-Fi     1

但是,当我尝试使用 groupby 函数时,pandas 会计算整个列表的出现次数,而不是分离其元素。我尝试了多种不同的方法来处理这个问题,使用元组或拆分,但到目前为止我还没有成功。

【问题讨论】:

旁白:pandas 目前还不完全支持非标量条目,使用它们时有时会出现神秘的故障。修改框架通常更安全,这样每一行都只包含标量条目。 【参考方案1】:

您也可以直接在列表中调用pd.value_counts。 您可以通过numpy.concatenateitertools.chaincytoolz.concat 生成相应的列表

from cytoolz import concat
from itertools import chain

cytoolz.concat

pd.value_counts(list(concat(df.categories.values.tolist())))

itertools.chain

pd.value_counts(list(chain(*df.categories.values.tolist())))

numpy.unique + numpy.concatenate

u, c = np.unique(np.concatenate(df.categories.values), return_counts=True)
pd.Series(c, u)

全部收益

Book          2
Electronic    1
Fantasy       1
Material      1
Sci-Fi        1
dtype: int64

时间测试

【讨论】:

谢谢@NickilMaveli...我错过了 ;-) 我感到困惑 ;-)【参考方案2】:

您可以通过堆叠记录来规范化记录,然后调用value_counts():

pd.DataFrame(df['categories'].tolist()).stack().value_counts()
Out: 
Book          2
Fantasy       1
Material      1
Sci-Fi        1
Electronic    1
dtype: int64

【讨论】:

【参考方案3】:

试试这个:

In [58]: df['categories'].apply(pd.Series).stack().value_counts()
Out[58]:
Book          2
Fantasy       1
Electronic    1
Sci-Fi        1
Material      1
dtype: int64

【讨论】:

@ayhan,你为什么要删除你的解决方案?我想它比我的好 @MaxU .apply(pd.Series) 似乎比 pd.DataFrame(ser.tolist()) 更明确。我的看起来像一个副作用,将来可能不会起作用。 @ayhan,但与df['categories'].apply(pd.Series) 相比,pd.DataFrame(df['categories'].tolist()) 很可能会更快。无论如何,为了完整起见(并有选择),我会要求你取消删除你的答案;-) 我都试过了。它们都可以工作,但“tolist()”变体似乎要快得多 @Skum,是的,我也比我更喜欢 ayhan 的解决方案! :-)

以上是关于Pandas:在列表的每个元素上使用 groupby的主要内容,如果未能解决你的问题,请参考以下文章

如果 pandas 系列的值是一个列表,如何获取每个元素的子列表?

Pandas列表的列,通过迭代(选择)三列的每个列表元素作为新列和行来创建多列[重复]

迭代 Pandas 分组数据框

在每个元素都是列表的数据帧中运行 Scipy Linregress

如何将元组列表转换为 pandas 数据框,以便每个元组的第一个值代表一列?

根据另一列从 Pandas 系列中的列表中选择元素