groupby()后调用mean()只返回数值列,因非数值列被静默忽略;可用select_dtypes('number')检查,需混合聚合时应改用agg()并传入字典指定各列函数。

groupby() 后直接调用 mean() 为什么只返回部分列
因为 groupby() 默认对所有数值列聚合,但如果你的 DataFrame 里混着字符串、时间或对象类型列,mean() 会自动跳过它们——不是报错,是静默忽略。你看到的“少列”,其实是非数值列被过滤掉了。
- 检查哪些列参与了计算:
df.select_dtypes(include='number').columns.tolist() - 想强制包含某列(比如把字符串当类别计数)?别用
mean(),改用agg()显式指定:.agg({'sales': 'mean', 'region': 'count'}) - 如果某数值列含
NaN,mean()默认跳过(skipna=True),但count()统计的是非空值个数,不是行数——这点和 SQL 的COUNT(*)不同
count() 和 size() 看起来一样,到底该用哪个
count() 是按列统计非空值数量,size() 是按组统计总行数(含 NaN)。差别就在缺失值上。
- 要算每组“有多少条记录”,无条件用
size()或count().sum(axis=1)——更准、更快 - 要算“某列在每组里填了多少个值”,才用
count('col_name') -
size()返回的是Series,索引就是分组键;count()返回DataFrame(多列时),列名保留原样 - 性能上,
size()不检查值内容,比count()快 2–3 倍,尤其数据量大时
agg() 里传字典 vs 传列表,结果结构差很多
传列表(如 ['mean', 'std'])会对所有可聚合列重复应用每个函数,列名变成多级索引;传字典(如 {'price': 'mean', 'qty': 'sum'})则精准控制每列行为,结果是扁平列名。
- 想要结果列名是
price_mean、qty_sum?必须用字典 +as_index=False,或者之后调用add_suffix() - 传列表时,如果某列不支持某个函数(比如对字符串用
mean),会直接丢弃该列,不报错 - 混合类型聚合(如同时要
mean和first)只能靠字典,列表不支持不同列不同函数
groupby().apply() 比 agg() 慢很多,什么情况非用不可
apply() 是通用接口,每次调用都走 Python 层循环,而 agg() 能触发底层 Cython 优化。除非你要做 agg() 不支持的事,否则别碰 apply()。
- 需要访问整组数据做计算(比如组内排序后取第 2 行):
.apply(lambda x: x.sort_values('t').iloc[1]) - 返回结构不固定(有时标量,有时 Series)——
agg()要求每组输出同构 - 想在聚合时顺便修改原始 DataFrame 的某些标记字段?
apply()可以,agg()不行 - 用
apply()前先确认:能不能拆成transform()+agg()?比如组内标准化就该用transform('std'),而不是apply()
真正难搞的是跨组依赖或状态累积类逻辑——那已经超出 groupby 能力边界了,得换思路,比如预排序 + shift() 或用 itertuples() 手动遍历。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











