You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pandas多列分组计算:多次groupby还是单次groupby内实现效率更高?

pandas按分组计算新增多列的性能问题解答

问题背景

在使用pandas开展数据处理时,假设需要为现有DataFrame新增A、B、C三列,每列都需要基于原有数据完成对应计算,且所有计算都需按照code列划分的行组执行,对比以下两种实现方式的运行速度:

  • 方式一:分三次调用groupby+apply,分别生成对应列:
df.groupby('code').apply(generate_A)
df.groupby('code').apply(generate_B)
df.groupby('code').apply(generate_C)
  • 方式二:仅调用一次groupby+apply,在传入的generate_A_B_C函数内对每个分组依次调用generate_A、generate_B、generate_C,一次性生成三列结果:
df.groupby('code').apply(generate_A_B_C)

以下为实际业务场景中的对应代码示例:

df['rsi_1_increases_above_lower_threshold_Close'] = df.groupby('SecuritiesCode').apply(detect_if_RSI_crosses_above_lower_threshold,
                                                                                                          rsi_lower_threshold = rsi_lower_threshold,
                                                                                                          rsi_column='rsi_1_Close')

df['rsi_1_decreases_below_upper_threshold_Close'] = df.groupby('SecuritiesCode').apply(detect_if_RSI_crosses_below_upper_threshold,
                                                                                                          rsi_upper_threshold = rsi_upper_threshold,
                                                                                                          rsi_column='rsi_1_Close')

结论

方式二的运行速度明显更快。

原因说明

  1. 避免了重复的分组构建开销
    每次调用groupby时,pandas都需要遍历全量数据,对分组键做哈希计算、拆分数据块、维护分组和行索引的映射关系,这部分操作在数据量越大、分组数量越多时开销越高。方式一需要重复执行3次完整的分组流程,方式二仅需执行1次。就算提前把分组对象缓存为变量(比如先执行g = df.groupby('code'),再三次调用g.apply()),省去了重复拆分分组的开销,依然存在其他额外成本。
  2. 减少了结果合并与索引对齐的重复开销
    每次apply执行完成后,pandas都需要把所有分组返回的计算结果做拼接,再和原DataFrame的索引做对齐,最终生成可以直接赋值给列的序列对象。方式一需要做3次结果拼接、索引对齐操作,方式二仅需做1次。
  3. 减少了分组数据的重复遍历
    方式一中每个分组的数据会被三次apply分别读取、计算三次,方式二中每个分组的数据仅需读取一次,就可以在同一个函数内完成所有字段的计算,数据读取层面的开销也更低。

内容的提问来源于stack exchange,提问作者Abhisek Dash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:09:10