pandas对列level1分配不同聚合函数实现分组聚合的问题
问题场景
现有如下多层列索引的DataFrame:
albumin bilirubin albumin bilirubin mean mean count count id class 142345 a 3.4 1.0 1.0 1.0 a 3.2 2.0 0.0 0.0 b 3.1 1.0 0.0 0.0 b 2.7 0.0 3.0 0.0
需求如下:
- 按行维度的
['id', 'class']层级做分组聚合 - 针对列索引的level 1层级匹配不同聚合规则:level值为
mean的列应用均值计算,level值为count的列应用求和计算 - 方案需要支持大量列的通用场景,无需硬编码列名
期望输出结果如下:
albumin bilirubin albumin bilirubin mean mean count count id class 142345 a 3.3 1.5 1.0 1.0 b 2.9 0.5 3.0 0.0
尝试编写如下代码实现:
def f(x): aggs = {"mean": np.mean, "count": np.sum} func = aggs.get(x.name, np.sum) return func(x) grouped=df.groupby(['id', 'class'], axis=0, level=1 ).apply(f)
运行后抛出报错:TypeError: 'Categorical' object is not callable,参考的同类方案无法直接适配当前场景。
实现方案
报错核心原因:传入apply的对象是每个分组对应的子DataFrame,此时x.name返回的是分组键值(即class字段的分类类型值),并非列的二级索引名,无法匹配到预设的聚合函数,触发类型错误。
通用实现代码如下,无需硬编码列名,可自动适配任意数量符合规则的列:
import pandas as pd import numpy as np # 配置列二级索引与聚合函数的映射关系,后续新增规则直接追加键值对即可 agg_rule = { "mean": np.mean, "count": np.sum } # 按行索引的id、class层级分组 df_group = df.groupby(level=["id", "class"]) # 按列二级索引拆分,分别应用对应聚合规则后拼接,还原多层列结构 result = pd.concat( [ df_group[df.columns[df.columns.get_level_values(1) == col_level]].agg(agg_func) for col_level, agg_func in agg_rule.items() ], axis=1 ) # 对齐原表列顺序 result = result[df.columns]
方案说明:
- 自动识别所有列的二级索引值,匹配对应聚合逻辑,无需手动指定
albumin/bilirubin等一级列名 - 后续新增二级索引规则时,只需要在
agg_rule字典中追加对应映射即可,比如要给二级索引为max的列应用最大值计算,直接添加"max": np.max即可 - 最终输出的列顺序和原表完全一致,不会出现列错位问题
内容的提问来源于stack exchange,提问作者jpetot
相关产品推荐
相关产品推荐

