微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

python – 计算列表列中包含的列表的出现的熊猫

我有这个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的列表也没有,因此它们可以是集合而不是列表.

我的程序的第一次迭代遍历每一行并检查所有(在数据[‘m’] [i]中为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]

一个辅助函数,它像我之前一样简单地返回包含布尔值:

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

然后我可以使用np.vectorize来添加一个带有布尔值的列:

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

最后,用简单的df [‘bool’]计算这些布尔值的总和.sum()

我也试过使用.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(),它们都在比Python等效的更低级别(通常为C级别)运行.

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

我不能看到更多的时间,而不是写一个自定义的C级函数,它相当于一个自定义和与检查有一个子集,以逐行确定0/1.在这一点上,你无论如何都可以运行成千上万次.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐