在Pandas中,统计列表列中所有值的总出现次数的更快方法是什么?

6

我有一个包含大量标签列表的pandas数据帧中的列:

>>> data['SPLIT'].head(10)
0    [33.23, 88.72, 38.93, E931.7, V09.0, 041.11, 5...
1    [99.04, 38.06, 39.57, 00.91, 55.69, V15.82, 27...
2    [96.04, 96.72, 401.9, 276.5, 584.9, 428.0, 507...
3    [96.6, 99.15, 99.83, V29.0, 765.15, 765.25, 77...
4    [96.71, 96.04, 54.12, 99.60, 38.93, 99.15, 53....
5    [88.72, 37.61, 39.61, 36.15, 36.12, 272.0, 401...
6    [38.93, 88.72, 37.31, 272.4, 719.46, 722.0, 31...
7    [88.72, 39.61, 35.71, 272.4, V12.59, 458.29, 7...
8    [97.44, 99.04, 88.56, 37.23, 39.95, 38.95, 00....
9    [00.14, 89.61, 39.95, E878.8, 244.9, 443.9, 18...

我希望能够遍历这些列表,并找到每个值的总出现次数,以便找到出现频率最高的50个值。
这是我使用的代码,运行非常缓慢:
test = pd.Series(sum([item for item in data.SPLIT], [])).value_counts()

我尝试编写一个函数在循环外部遍历列表并计算数量,但这也非常慢。

是否有任何方式可以修改这些数据或使用pandas中类似于df.groupby.count()的函数来实现类似的性能?

我在谷歌和stackoverflow上搜索了半个小时,但没有一个答案具有更好的性能。我已经尝试了很长时间以找到一种方法来展平列表或找到一种映射计数的更快速的方法(迭代500k行,每个列表的长度都不同,有的可以长达512,有的只有2)。

2个回答

9

使用列表推导式进行扁平化,而不是使用 sum

test = pd.Series([x for item in data.SPLIT for x in item]).value_counts()

使用chain.from_iterable进行扁平化:

from itertools import chain

test = pd.Series(list(chain.from_iterable(data.SPLIT))).value_counts()

或者也可以使用collections.Counter

from itertools import chain
from collections import Counter

test = pd.Series(Counter(chain.from_iterable(data.SPLIT)))

或者:

import functools, operator

test = pd.Series(functools.reduce(operator.iconcat, data.SPLIT, [])).value_counts()

纯pandas解决方案:

test = pd.DataFrame(data.SPLIT.values.tolist()).stack().value_counts()

1
天啊,伙计,那个第一个解决方案看起来几乎和我写的一样,但它几乎瞬间完成了。非常感谢。我会弄清楚为什么你的速度快那么多,感谢你的指导。 - Ben C Wang
@BenCWang - 请查看这个链接 - 我还添加了最快的解决方案。 - jezrael

2
最初的回答是怎样的?
这个怎么样?
import pandas as pd

split = data["SPLIT"].apply(pd.Series)
split = split.rename(columns = lambda x : 'val_' + str(x))
split.melt(value_name="val").groupby(["val"]).size()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接