【问题标题】:High performance apply on group by pandas高性能适用于熊猫分组
【发布时间】:2020-02-09 07:51:06
【问题描述】:

我需要计算熊猫数据框列的百分位数。数据框的一个子集如下:

我想计算 SaleQTY 的第 20 个百分位,但对于 ["Barcode","ShopCode"] 的每一组: 所以我定义了一个函数如下:

def quant(group):
    group["Quantile"] = np.quantile(group["SaleQTY"], 0.2)
    return group

并将此函数应用于我的销售数据的每个组,该数据有近 1800 万行和大约 300 万组 ["Barcode","ShopCode"]:

quant_sale = sales.groupby(['Barcode','ShopCode']).apply(quant)

在具有 128 GB 内存和 32 核的 Windows 服务器上完成这需要 2 小时。 这是没有意义的,因为那只是我代码的一小部分。所以我开始搜索网络以提高性能。 我想出了以下代码的“numba”解决方案,但不起作用:

from numba import njit, jit
@jit(nopython=True)
def quant_numba(df):
    final_quant = []
    for bar_shop,group in df.groupby(['Barcode','ShopCode']):
        group["Quantile"] = np.quantile(group["SaleQTY"], 0.2)
        final_quant.append((bar_shop,group["Quantile"]))
    return final_quant    
result = quant_numba(sales)  

似乎我不能在这个装饰器中使用 pandas 对象。

我不确定是否可以使用多处理(我不熟悉整个概念)或者是否有任何解决方案可以加快我的代码速度。因此,我们将不胜感激。

【问题讨论】:

  • 一种方法是在条形码/商店代码上对数据集进行分区,并使用多处理对分区数据集应用 quant 函数。其他方法是使用诸如 Modin/Dask/Celery 或使用 Spark 之类的东西来带出大炮
  • 您是否尝试过保持简单并执行以下操作:df['Quantile'] = df.groupby(['Barcode', 'Shopcode'])['SaleQTY'].transform('quantile', q=0.2)
  • @skybunk 谢谢...我应该明确定义每个分区吗?你能给我一个关于定义分区的提示吗?然后我想我可以得到map_partition的帮助。我说的对吗?

标签: python pandas performance apply


【解决方案1】:

你可以试试DataFrameGroupBy.quantile:

df1 = df.groupby(['Barcode', 'Shopcode'])['SaleQTY'].quantile(0.2)

或者像提到的@Jon Clements 一样,对于由百分位数填充的新列使用GroupBy.transform

df['Quantile'] = df.groupby(['Barcode', 'Shopcode'])['SaleQTY'].transform('quantile', q=0.2)

【讨论】:

  • 我在想什么......但后来不确定他们想要做的是转换(正如我在评论中所说)还是这个......我猜这更有可能: )
  • @JonClements - 谢谢,经过测试并为新专栏工作很好。
  • 谢谢@jezrael ...克服我的好奇心...这个简单的应用内置功能的背后是什么,可以在不到一分钟的时间内完成整个过程?因为在我定义的“量化”函数中,我还使用了 numpy 内置函数(np.quantile)
  • @mpy - 我认为原因是熊猫是 numba、numpy 中每个组的优化函数,速度非常快。
  • @mpy apply 是通用的,有额外的 Python 调用开销,它可以返回需要广播/扩展等的不同结果类型......并且由于这种灵活性,它有相当多的工作量以及产生最终结果所需的分位数...但是,内置函数具有明确定义的结果,并且操作符在基本级别上更多,因此可以快得多
【解决方案2】:

panda 中有一个内置函数,叫做 quantile()。

quantile() 将有助于获取 df 中列的第 n 个百分位数。

文档参考link

geeksforgeeks 示例reference

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多