【问题标题】:Pandas groupby: straight-forward counting the number of elements in each group is very slowPandas groupby:直接计算每组中的元素数量非常慢
【发布时间】:2014-03-06 19:25:06
【问题描述】:

我需要一些分箱数据的统计信息。 我认为pandas groupby 方法将是一种非常自然的方法。

为了提高性能,我意识到从传递给agg 的列表中删除count 方法会显着提高。

令我惊讶的是,从总和/平均值的比率中提取计数会带来显着的改进。 在我的实际应用中,这导致计算时间缩短了 100 倍

我想知道我是否以某种方式滥用了代码。

在下面你可以找到一个人工的例子:

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: df = pd.DataFrame({'x':np.random.randn(5000), ## produce the demo DataFrame 
   ...:                    'y':np.random.randn(5000),
   ...:                    'z':np.random.randn(5000)})

In [4]: buckets = {col : np.arange(int(df[col].min()) ,int(df[col].max())+2) 
   ...:            for col in df.columns} ## produce the unit bins

In [5]: cats = [pd.cut(df[col], bucket) for col,bucket in buckets.iteritems()]

In [6]: grouped = df.groupby(cats) # group by the binned x,y,z

In [7]: %%timeit
   ...: fast_count = grouped.x.agg(['sum','mean','var'])
   ...: fast_count = (fast_count['sum']/fast_count['mean'] + 0.5).astype(np.int)   ...: 
1000 loops, best of 3: 1.06 ms per loop

In [8]: %%timeit
   ...: slow_count = grouped.x.count()
   ...: 
100 loops, best of 3: 18.9 ms per loop

In [9]: fast_count = grouped.x.agg(['sum','mean','var'])

In [10]: fast_count = (fast_count['sum']/fast_count['mean'] + 0.5).astype(np.int)

In [11]: slow_count = grouped.x.count()

In [12]: (fast_count != slow_count).sum()
Out[12]: 0

In [13]: (fast_count == slow_count).sum()
Out[13]: 204

感谢 Jeff 的回复(下),更优雅的代码(显示可比性能):

In [17]: %%timeit
   ....: another_fast_count = grouped.x.size()
   ....: 
1000 loops, best of 3: 609 µs per loop

请参阅 Jeff 回复后的 cmets 以获得一些解释

NB(基于hayd's comment):

count 只计算非空元素,而size 不会区分。 这可能是性能差异的原因。 因此,应谨慎选择这两个选项。

【问题讨论】:

    标签: python count group-by pandas


    【解决方案1】:

    尝试使用.sizecount 进入python空间进行实际计算;而size 使用的是预先计算的组数据。在大小方面实现count 可能是一个不错的 PR(以避免这种混淆)。

    In [8]: %timeit grouped.x.size()
    1000 loops, best of 3: 500 ᄉs per loop
    
    In [9]: %timeit grouped.x.count()
    100 loops, best of 3: 19.4 ms per loop
    
    In [10]: grouped.x.size().equals(grouped.x.count())
    Out[10]: True
    

    【讨论】:

    • size 比我的解决方案优雅得多(因此 +1);谢谢!仍然 - 无法将它传递给 agg 的函数列表中的 count(和 meansum、...)。知道现在实施count 的方式有什么优势吗?
    • count 委托给底层框架。 mean,sum 等一些功能在 cython 中实现得非常快。 size 实际上是一个特殊的,一旦你 groupby 就已经完成了。我将创建一个问题来解决这个问题;本质上需要计算调用大小;可能存在无法在聚合器中使用的错误。
    • 感谢您的解释和打开 github 问题!
    猜你喜欢
    • 2019-09-30
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 2019-01-03
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多