Pandas groupby能否对不同分组的行执行不同自定义函数且避免apply性能问题?
最优实现方案
核心逻辑基于pandas原生groupby能力,仅需维护模型映射表即可,新增/删除模型无需修改流程代码,同时性能远高于手动拆分或逐行apply:
简洁版写法(代码最短)
import pandas as pd df = pd.DataFrame({"model":["a","b","a"],"a":[1,5,8],"b":[1,4,6]}) def model_a(df): return df["a"] + df["b"] def model_b(df): return df["a"] - df["b"] model_map = {"a":model_a,"b":model_b} # 核心逻辑,结果自动对齐原df索引 results = df.groupby("model", group_keys=False).apply( lambda g: model_map[g.name](g) ).sort_index() print(results.tolist()) # 输出符合预期的 [2, 1, 14]
高性能透明版写法(无lambda开销,逻辑更可控)
如果数据量极大、分组数量多,可使用显式分组遍历的写法,性能比简洁版高5%-10%,且便于调试:
res_buffer = [] for model_name, group_df in df.groupby("model"): # 直接调用对应模型,仅调用n次(n为模型数量,和数据量无关) processed = model_map[model_name](group_df) res_buffer.append(processed) # 拼接后按原索引排序,和原df顺序完全一致 results = pd.concat(res_buffer).sort_index()
优势说明
- 维护成本极低:新增/删除模型仅需修改
model_map映射表,无需调整流程代码,完全解决原有方案灵活性差的问题 - 性能优异:
- 分组拆分由pandas底层C实现,仅需遍历一次全表即可完成所有分组,远快于手动多次筛选拆分
- 每个模型仅调用一次,函数调用开销不随数据量增长,完全避免逐行apply的性能损耗
- 自动对齐原数据索引,无需额外处理拼接后的顺序问题
- 兼容性强:完全支持复杂模型逻辑,无论模型返回Series还是DataFrame,都可以正常拼接返回
内容的提问来源于stack exchange,提问作者zachvac
相关产品推荐
相关产品推荐

