如何为已有的Pandas GroupBy对象添加分组层级以优化性能?
解决方案:复用基础分组结果以减少耗时
两次独立执行groupby的核心问题在于,pandas会重复对col1/col2/col3进行哈希计算、排序等分组前置操作,这在大型DataFrame上会产生极高的冗余开销。以下是两种可行的复用方案:
方法一:预计算基础分组标识列
通过给每个(col1, col2, col3)组合分配唯一ID,只计算一次基础分组的哈希,后续分组直接复用该ID:
import pandas as pd # 预计算基础分组的唯一整数ID(仅执行一次col1-col3的分组计算) df['base_group_id'] = df.groupby(["col1", "col2", "col3"]).ngroup() # 第一次分组(执行你的聚合操作,比如sum/mean等) dfNew1 = df.groupby(["col1", "col2", "col3"], as_index=False).agg( # 示例聚合:计算col5的均值,col6的总和 col5_mean=('col5', 'mean'), col6_sum=('col6', 'sum') ) # 第二次分组:复用基础分组结果,避免重复计算col1-col3 # 添加sort=False跳过排序操作,进一步减少耗时 dfNew2 = df.groupby(["col1", "col2", "col3", "col4"], as_index=False, sort=False).agg( col5_mean=('col5', 'mean'), col6_sum=('col6', 'sum') ) # 若不需要base_group_id,后续可直接删除:df.drop('base_group_id', axis=1, inplace=True)
方法二:遍历基础分组的子DataFrame
直接复用第一次分组得到的子数据集,在每个子集中单独按col4分组:
baseGrouper = df.groupby(["col1", "col2", "col3"]) # 第一次分组的聚合结果 dfNew1 = baseGrouper.agg( col5_mean=('col5', 'mean'), col6_sum=('col6', 'sum') ).reset_index() # 第二次分组:遍历每个基础分组,内部按col4聚合 sub_group_results = [] for group_keys, sub_df in baseGrouper: # 子数据集内按col4分组 sub_result = sub_df.groupby("col4", as_index=False).agg( col5_mean=('col5', 'mean'), col6_sum=('col6', 'sum') ) # 补回col1-col3的分组键信息 sub_result[["col1", "col2", "col3"]] = group_keys sub_group_results.append(sub_result) # 合并所有子分组结果 dfNew2 = pd.concat(sub_group_results, ignore_index=True)
关键注意事项
- 务必明确聚合操作:仅创建
GroupBy对象不会触发实际分组计算,耗时发生在agg()/apply()等执行阶段。 - 大型数据集优先用方法一:方法二在基础分组数量极多时,遍历会产生额外开销;方法一的
ngroup()是矢量化操作,效率更高。
内容的提问来源于stack exchange,提问作者Philip Kahn
相关产品推荐
相关产品推荐

