pandas groupby使用agg命名聚合速度极慢的原因是什么?
问题原因分析
你遇到的性能差距本质是自定义聚合函数触发了Python层逐分组回调,无法调用pandas底层优化的Cython实现。
你当前的写法中,lambda属于Python自定义函数,当分组量级达到30万级别时,几十万次Python函数调用的开销会被显著放大,这就是耗时提升200倍的核心原因。
而直接调用groupby.sum()方法时,pandas会直接走Cython实现的聚合逻辑,完全没有Python层的回调开销,所以速度极快。
另外你尝试的functools.partial属于Python层的函数封装,依然会触发逐分组Python调用,因此性能没有提升。
高性能解决方案
你不需要使用lambda包裹聚合逻辑,pandas的命名聚合支持直接传入内置聚合函数的字符串标识符,同时支持给聚合函数传递额外参数,两种可落地的方案如下:
方案1:命名聚合语法直接传内置聚合标识
直接用字符串'sum'代替lambda,同时将min_count作为agg方法的参数传入,pandas会自动将该参数传递给所有聚合函数,同时走Cython优化路径,性能和直接调用groupby.sum完全一致:
df.groupby('A').agg(**{ 'newname' : ('B', 'sum') }, min_count=1)
如果是多列不同参数的聚合,也可以用pd.NamedAgg明确指定参数:
df.groupby('A').agg( newname=pd.NamedAgg(column='B', aggfunc='sum', min_count=1) )
方案2:先聚合再重命名列
如果不需要同时对多列做不同规则的聚合,直接调用优化的sum方法后重命名列,写法更简洁,性能同样最优:
# 单列聚合场景 df.groupby('A')['B'].sum(min_count=1).to_frame(name='newname') # 多列聚合场景 df.groupby('A').sum(min_count=1).rename(columns={'B': 'newname'})
以上两种方案的耗时都和你直接调用groupby.sum的0.11秒基本一致,同时可以满足业务命名需求。
内容的提问来源于stack exchange,提问作者Rens
相关产品推荐
相关产品推荐

