groupby.filter() 与 df.query() 核心区别
1.本质定位完全不同
① df.query(条件字符串)
整表行筛选:按单行字段过滤,不分组
逐行判断条件,满足就保留本行,每行独立运算,看不到同组其他数据
python
# 单条数据score>20就留下该行,和其他行无关
res = df.query("score > 20")
适用:基于自身行字段筛选数据。
② groupby().filter(func)
分组筛选:先分组 → 对整组数据做条件,整组留/整组删
- 按
player_id拆分成N个子DataFrame(每个玩家一组) - lambda入参
x=单组完整子df;len(x)>=3:本组行数≥3 → 保留该组全部数据;否则整组全部剔除 - 返回:所有符合条件分组的原始明细数据(原样行,不聚合)
python
# 保留出场次数>=3次的玩家所有明细,出场<3整个人所有数据全删掉
filtered = df.groupby('player_id').filter(lambda x: len(x) >= 3)
适用:**按组统计特征过滤整组数据(统计每组数量、均值、最值再筛选),注意:groupby.filter 返回原始明细行,不是聚合汇总表(不会只返回 A、C 一行统计数),这是因为链式调用 .filter 后直接变回普通 DF
**
2.关键对比表
| 特性 | query() | groupby.filter() |
|---|---|---|
| 筛选粒度 | 单行 | 整组 |
| 能否使用同组聚合信息 | ❌不能(看不到同组别的行) | ✅可以(x是全组数据,可len/mean/max) |
| 返回格式 | 原表子集(符合条件单行) | 原表子集(符合条件的整组所有行) |
| 书写形式 | 字符串表达式,简单 | lambda函数,可复杂逻辑 |
3.实操例子区分
数据:
| player_id | score |
|---|---|
| p1 | 10 |
| p1 | 20 |
| p2 | 15 |
df.query("score>15"):只剩p1,20一行(单行分数达标)df.groupby('player_id').filter(lambda x:len(x)>=2):只剩p1两条(p1一共2行,整组保留;p2仅1行整组删除)
4.补充常用替换
想要分组筛选不用filter:搭配merge
python
# 先算出满足条件id,再匹配原数据
valid_id = df.groupby('player_id').size().reset_index(name='cnt').query("cnt>=3")['player_id']
res = df[df['player_id'].isin(valid_id)]
# 等价groupby.filter(lambda x:len(x)>=3)
一句话总结
- query:挑合格的行
- groupby.filter:挑合格的组,整组带走
三大 groupby 链式函数返回区别(必背)
- 聚合 .sum ()/.count ()/.size () → Series / DF(汇总统计)
- transform →和原表行数一致的 Series(附加统计列)
- filter → 原结构 DF,筛选整组数据,剔除不达标分组的全部明细