pandas.groupby().agg()应避免字典值用list,改用named aggregation;groupby默认dropna=true需显式设置;慎用apply,优先内置方法;as_index=false隐性拷贝耗内存,建议reset_index()。

用 pandas.groupby().agg() 时别直接传字典套 list
常见错误是写成 df.groupby('key').agg({'col': ['mean', 'std']}),看似简洁,但内部会触发多重路径判断和冗余计算,尤其在列多、聚合函数多时,性能掉得明显。
实操建议:拆成明确的 named aggregation 写法,让 pandas 提前知道每个输出列名和对应函数,跳过推导逻辑:
df.groupby('key').agg(
mean_val=('col', 'mean'),
std_val=('col', 'std')
)
- 避免用
['mean', 'std']这种 list 形式——它强制 pandas 启动旧式聚合引擎 - 如果必须复用函数逻辑,优先封装为
lambda或命名函数,再传入 tuple,不要塞进 dict value 里 - 注意:Pandas ≥1.3 才完整支持 named aggregation;老版本会静默回退到慢路径
groupby 前先 dropna=False 还是默认丢?
默认情况下 groupby 会自动丢弃 NaN 的分组键(即 dropna=True),这常导致结果行数比预期少,且不易察觉——特别是当你的业务逻辑本该包含空分组时。
实操建议:明确声明 dropna 参数,别依赖默认值:
立即学习“Python免费学习笔记(深入)”;
- 要保留空键分组 → 加
dropna=False,否则NaN键全被过滤,size()和count()行为也不同 -
count()本身不计NaN,但size()计;混用时容易误判“缺失”是数据问题还是分组被删了 - 如果后续要 merge 回原表,没设
dropna=False可能导致 key 对不上,报KeyError或静默丢行
大表聚合卡住?检查是否意外触发 apply 回退
当你写 df.groupby('key').apply(lambda x: x.sort_values('time').tail(1)),看起来只是取每组最新一条,但只要 lambda 里用了非标量操作或返回结构不一致,pandas 就会放弃向量化路径,切到慢得多的 Python 循环模式。
实操建议:优先用内置方法替代 apply:
- 取每组最新/最旧 → 用
idxmax()/idxmin()配合.loc,比如df.loc[df.groupby('key')['time'].idxmax()] - 需要复杂排序后取值 → 先
sort_values整体排,再用groupby(...).head(1),比apply快 5–10 倍 - 确认是否真需要
apply:打印type(result),如果是Series或DataFrame且 shape 不统一,基本已掉进回退陷阱
聚合后内存暴涨?小心 as_index=False 的隐性拷贝
很多人加 as_index=False 是为了图方便省去 reset_index(),但它会让 pandas 在聚合阶段就构造新 DataFrame,而不是复用原有索引结构,对大表来说等于白多占一份内存。
实操建议:按需选择索引策略,别无脑关:
- 后续还要继续 groupby 或 join → 保持默认
as_index=True,索引就是天然分组标识,更省内存 - 必须输出平铺表结构 → 用
reset_index()显式调用,比as_index=False更可控,也方便链式调试 - 聚合列名含特殊字符或重复名时,
as_index=False可能引发ValueError: cannot insert xxx, already exists,而reset_index()能提前暴露问题
真正影响性能的往往不是聚合函数本身,而是你没意识到 pandas 正在为你悄悄做哪些事——比如重排索引、推断类型、补全缺失分组。这些动作在小数据上无感,一到百万行以上,延迟和内存就全堆在看不见的地方。











