gpt4 book ai didi

python - Pandas 计算列表列中包含的列表的出现次数

转载 作者:太空狗 更新时间:2023-10-30 02:54:02 24 4
gpt4 key购买 nike

我有这个 Pandas DataFrame,其中有一列包含列表:

>>> df = pd.DataFrame({'m': [[1,2,3], [5,3,2], [2,5], [3,8,1], [9], [2,6,3]]})
>>> df
m
0 [1, 2, 3]
1 [5, 3, 2]
2 [2, 5]
3 [3, 8, 1]
4 [9]
5 [2, 6, 3]

我想计算列表 v = [2, 3] 包含在 DataFrame 列表中的次数。所以在这个例子中正确的答案是3。现在这只是一个示例,在我的实际数据中,df['m'] 可以包含超过 900 万行,列表实际上是包含最多约 20 个元素的字符串列表。如果重要,请提供更多详细信息:v 的元素不包含重复项,m 的列表也不包含重复项,因此它们可以是集合而不是列表。

我的程序的第一次迭代遍历每一行并检查 all(e in data['m'][i] for e in v) 如果是,我会增加一个计数器。但是正如许多 SO 问题和博客文章中提到的那样,遍历 DataFrame 的行很慢,但可以更快地完成。

因此,对于我的下一次迭代,我向 DataFrame 添加了一列,其中包含列表 v 的副本:

>>> df['V'] = [[2, 3]] * len(df)
>>> df
V m
0 [2, 3] [1, 2, 3]
1 [2, 3] [5, 3, 2]
2 [2, 3] [2, 5]
3 [2, 3] [3, 8, 1]
4 [2, 3] [9]
5 [2, 3] [2, 6, 3]

还有一个辅助函数,它像我之前所做的那样简单地返回包含 bool 值:

def all_helper(l1, l2):
return all(v in l1 for v in l2)

然后我可以将其与 np.vectorize 一起使用以添加具有 bool 值的列:

df['bool'] = np.vectorize(all_helper)(df['m'], df['V'])

最后,使用简单的 df['bool'].sum()

计算这些 bool 值的总和

我还尝试使用 .apply():

df['bool'] = df.apply(lambda row: all(w in row['m'] for w in v), axis=1)
count = df['bool'].sum()

但这比矢量化慢。

现在这些方法起作用了,向量化比最初的方法快得多,但感觉有点笨拙(创建一个具有相同值的列,以这种方式使用辅助函数)。所以我的问题是,性能是关键,是否有更好/更快的方法来计算列表列中包含列表的次数?由于列表不包含重复项,也许检查如果 len(union(df['m'], df['V'])) == len(df['m']) 之类的,但我不知道如何以及是否是最佳解决方案。

编辑:因为有人问;这是一个使用字符串而不是整数的示例:

>>> df = pd.DataFrame({'m': [["aa","ab","ac"], ["aa","ac","ad"], ["ba","bb"], ["ac","ca","cc"], ["aa"], ["ac","da","aa"]]})
>>> v = ["aa", "ac"]
>>> df
m
0 ["aa", "ab", "ac"]
1 ["aa", "ac", "ad"]
2 ["ba", "bb"]
3 ["ac", "ca", "cc"]
4 ["aa"]
5 ["ac", "da", "aa"]

>>> count_occurrence(df, v)
3

但是如果你想要一个更广泛的DataFrame,你可以用这个来生成它:

import string

n = 10000
df = pd.DataFrame({'m': [list(set([''.join(np.random.choice(list(string.ascii_lowercase)[:5], np.random.randint(3, 4))) for _ in range(np.random.randint(1, 10))])) for _ in range(n)]})
v = ["abc", 'cde']
print(count_occurrence(df, v))

编辑:Divakar 或 Vaishali 的解决方案都不比使用 np.vectorize 的解决方案快。不知道是否有人能打败它。

Jon Clements 提出了一个大约快 30% 且更简洁的解决方案:df.m.apply(set(v).issubset).sum()。我继续寻找更快的实现,但这是朝着正确方向迈出的一步。

最佳答案

您可以使用 DataFrame.apply 以及内置的 set.issubset 方法,然后使用 .sum(),它们都以较低的速度运行水平(通常是 C 水平)比 Python 同等水平。

subset_wanted = {2, 3}
count = df.m.apply(subset_wanted.issubset).sum()

我看不出比编写一个自定义的 C 级函数节省更多的时间,它相当于一个自定义的 sum 和一个检查有一个子集 逐行确定 0/1。到那时,您无论如何都可以运行此程序成千上万次。

关于python - Pandas 计算列表列中包含的列表的出现次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47417474/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com