pandas中agg一次计算多个统计量需区分dataframe与series:dataframe支持字典映射(如{'a':'sum','b':'mean'}),series仅支持列表或单函数;命名元组语法(如a_sum=('a','sum'))可避免multiindex列名问题。

用 agg 一次算多个统计量,必须传 dict 或 list
直接传 {'A':'sum', 'B':'mean'} 是对的,但很多人卡在结果结构不对或报错。根本原因是:pandas 对 agg 的输入类型敏感,dict 只在 DataFrame 上支持「列 → 函数」映射;Series 不认这个写法。
- DataFrame 调用时,
agg({'A':'sum', 'B':'mean'})会返回新 DataFrame,列名不变,值为对应聚合结果 - Series 调用时,不能传 dict,只能传 list(如
['sum', 'mean'])或单个函数名 - 如果列名不在原始 DataFrame 中(比如用了
groupby后选了子集),会静默跳过,不报错也不警告
agg 里混用函数、字符串、lambda,怎么写才不崩
字符串(如 'mean')最省事,但没法传参数;函数(如 np.mean)灵活,但要注意签名;lambda 容易写错作用域。关键不是“能不能”,而是“返回值形状是否匹配”。
- 所有聚合函数必须返回标量(scalar),不能返回 Series 或数组,否则
agg会报ValueError: Must produce aggregated value - 用 lambda 时别直接写
lambda x: x.sum()—— 这没问题;但写lambda x: x.describe()就崩,因为返回的是 Series - 想传参数?用
functools.partial(np.quantile, q=0.9),别用lambda x: np.quantile(x, q=0.9),后者在多列聚合时可能触发广播错误
groupby 后用 agg,列名自动变成元组?怎么还原
这是最常被吐槽的点:一用 agg({'A':['sum','count'], 'B':'mean'}),列就变成 ('A', 'sum') 这种 MultiIndex,后续取列麻烦。不是 bug,是 pandas 默认行为 —— 它得区分不同聚合来源。
- 加参数
as_index=False不起作用,那是给groupby本身的,不影响agg输出结构 - 真正管用的是
agg(...).columns = ['A_sum', 'A_count', 'B_mean'],手动展平 - 更稳妥的是用命名元组写法:
agg(A_sum=('A','sum'), A_count=('A','count'), B_mean=('B','mean')),pandas 1.4+ 支持,输出列名就是你指定的字符串
性能差异大不大?agg 比循环 or 多次调用慢吗
慢,但只在小数据上明显。pandas 内部对 dict/list 输入做了路径优化,但本质仍是逐列 apply。真正拖慢的是函数本身 —— 特别是自定义 lambda 或调用低效的 numpy 函数。
- 用字符串名(
'sum')比用函数对象(np.sum)略快,因为跳过了函数查找和调用开销 - 避免在
agg里做重复计算,比如agg({'x':lambda s: s.max()-s.min(), 'y':lambda s: s.max()-s.min()}),应该先算再复用 - 如果聚合逻辑复杂且数据量大(>100 万行),考虑用
numba.jit加速单个函数,或者改用polars替代
agg(A_total=('A','sum')) 就能避开。还有就是 Series 和 DataFrame 对 agg 输入要求完全不同,混用时连错误信息都不提示,只默默返回奇怪结果。










