在使用 pandas 做数据统计时,groupby + agg 是绕不开的操作。
但很多人(包括我自己)在实际项目中都会遇到一个问题:
为什么明明只是做个统计,结果 dataframe 却变成了 multiindex,
后面 merge、导 excel、画图全都开始报错?
追根溯源,问题往往出在:
👉 groupby + agg 的写法选错了
本文结合真实工程经验,详细讲清楚 pandas 中 agg 的两种常见写法,以及为什么在工程场景下强烈推荐其中一种。
一、一个非常真实的使用场景
假设你在做检测评测统计,有如下数据:
| class | part1 | tp | fp | fn | gt_count |
|---|---|---|---|---|---|
| cow | v01 | 5 | 1 | 0 | 6 |
| cow | v01 | 4 | 0 | 1 | 5 |
| dog | v02 | 3 | 2 | 1 | 4 |
目标是:
按 class + part1 统计 tp / fp / fn / gt 数量
二、第一种写法:很多人最常用,但最容易踩坑
groupby_df = df.groupby(['class', 'part1']).agg(
{'tp': 'sum', 'fp': 'sum', 'fn': 'sum', 'gt_count': 'sum'}
)
这段代码有问题吗?
没有。
但它返回的结果结构是:
- class 和 part1 变成了 multiindex
- 统计结果才是列
也就是说,你拿到的是一张 多级索引 dataframe。
multiindex 在工程中会带来什么问题?
以下问题你大概率都会遇到:
- 导出 excel 前必须 reset_index()
- 和其他表 merge 时经常报错
- 新同事很难快速理解数据结构
- 后面再算指标时代码变得很别扭
👉 分析阶段还能接受,工程阶段非常痛苦
三、第二种写法:pandas 官方推荐(强烈建议)
groupby_df = (
df.groupby(['class', 'part1'], as_index=false)
.agg(
tp=('tp', 'sum'),
fp=('fp', 'sum'),
fn=('fn', 'sum'),
gt=('gt_count', 'sum'),
)
)
返回结果是什么样?
class | part1 | tp | fp | fn | gt
- 分组字段是普通列
- 没有 multiindex
- 看起来就是一张“标准统计表”
四、两种写法的核心区别对比
| 对比点 | 第一种写法 | 第二种写法 |
|---|---|---|
| 分组字段位置 | index | 普通列 |
| 索引类型 | multiindex | 普通 index |
| 是否需要 reset_index | 是 | 否 |
| 列名是否可控 | 否 | 是 |
| 扩展复杂统计 | 不优雅 | 非常自然 |
| 工程实用性 | 较低 | 很高 |
五、真实项目中的差距会越来越大
当统计需求升级,比如你还想算:
- 平均置信度
- 唯一 track 数
第一种写法会越来越臃肿:
df.groupby(['class', 'part1']).agg({
'tp': 'sum',
'fp': 'sum',
'fn': 'sum',
'score': 'mean',
'track_id': 'nunique'
})
而第二种写法依然清晰:
df.groupby(['class', 'part1'], as_index=false).agg(
tp=('tp', 'sum'),
fp=('fp', 'sum'),
fn=('fn', 'sum'),
avg_score=('score', 'mean'),
track_cnt=('track_id', 'nunique'),
)
到此这篇关于pandas中groupby+agg的两种写法区别小结的文章就介绍到这了,更多相关pandas中groupby+agg 内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论