用 groupby + agg 是最灵活、最可控的分组聚合方式,支持多列不同函数、自定义列名、精准定位类型错误,避免隐式丢列和 dtype 意外变化。

直接说结论:用 groupby + agg 是最灵活、最可控的分组聚合方式,比直接调 sum()、mean() 等方法更能处理多列不同函数、重命名结果、避免隐式类型转换等问题。
为什么不能只用 df.groupby(...).sum()
这种写法看似简单,但会强制对所有数值列调用 sum,且无法指定某列用 max、另一列用 count;更麻烦的是,它会把非数值列(比如字符串)静默丢弃,还不报错——你可能根本没意识到数据被砍掉了。
实操建议:
- 只要聚合逻辑不是“全部列统一用同一个函数”,就别用
.sum()/.mean()这类快捷方法 - 想保留原始列名并自定义新列名?
agg支持元组和字典语法,sum不支持 - 遇到
TypeError: cannot perform sum with type object?大概率是某列混了字符串或None,而.sum()没提示就跳过了,agg配合明确列名能帮你快速定位哪一列出问题
agg 的三种常用写法及适用场景
核心差异在「控制粒度」:你是想给所有列套一个函数,还是逐列指定,或是混合使用。
假设 df 有列 'category'、'sales'、'profit'、'region':
-
全列同函数:
df.groupby('category').agg('sum')—— 简单但粗糙,'region'(字符串)会被自动忽略 -
按列指定函数:
df.groupby('category').agg({'sales': 'sum', 'profit': 'mean', 'region': 'first'})—— 最常用,安全,可读性强 -
一列多个函数 + 重命名:
df.groupby('category').agg(sales_total=('sales', 'sum'), profit_avg=('profit', 'mean'))—— Pandas 0.25+ 支持,结果列名清晰,避免MultiIndex带来的取数麻烦
容易踩的坑:NaN 和 dtype 意外变化
agg 默认不跳过 NaN?错。像 'sum'、'mean' 这些内置函数默认 skipna=True,但你自己传的 lambda 或自定义函数不会自动跳,容易得到 NaN 结果却不知原因。
另一个隐形问题:agg 可能改变列的 dtype。例如 'sales' 是 int64,但用 'mean' 聚合后变成 float64;如果后续要做 merge 或存 CSV,得提前留意。
实操建议:
- 不确定数据有没有
NaN?先跑df.groupby(...).agg({'col': 'count', 'col': 'size'})对比,count不计NaN,size计,差值就是缺失数 - 需要保留整型结果?对
mean后的结果手动.round().astype('int'),但注意这会掩盖真实小数信息 - 聚合后列名变成
MultiIndex?优先用命名元组语法(如('sales', 'sum'))或字典键值对,避开老式元组列表写法
性能提醒:别在 agg 里写复杂 lambda
像 df.groupby('id').agg(lambda x: x.max() - x.min()) 看似简洁,但 Pandas 会为每组单独调用 Python 函数,速度比内置函数慢几倍到几十倍,尤其数据量超 10 万行时明显卡顿。
实操建议:
- 优先用字符串函数名(
'min'、'std'),Pandas 内部走优化路径 - 必须用自定义逻辑?先尝试
apply+ 向量化操作(如np.where、.clip),再进agg - 真要嵌套计算?拆成两步:
groupby得中间结果 → 新增列 → 再一次groupby.agg,往往比一步到位快
真正难的不是写对语法,而是想清楚“这一列该不该参与聚合”“缺失值在这里代表什么含义”“下游系统能否接受 float 类型 ID”。这些没法靠文档解决,得看数据本身长什么样。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











