You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas一行代码按分组均值筛选DataFrame

Pandas高效筛选分组内满足列值与分组均值条件的行

嘿,你提到的循环拼接方法确实能解决问题,但Pandas有更地道、高效的写法——用groupby.transform()结合布尔索引,完全不用手动循环拼接,代码简洁还能充分利用Pandas的向量化性能。

核心思路:用transform生成逐行对应的分组均值

transform()会把分组计算的结果(比如均值)广播到原DataFrame的每一行,这样我们就能直接把原列的值和对应的分组均值做逐行比较,再用布尔索引筛选出符合条件的行。

示例1:筛选C1列值≥分组均值的行

import pandas as pd

df = pd.DataFrame({
    "Group": ["A", "A", "A", "B", "B", "C"], 
    "C1": [1, 2, 3, 2, 3, 1], 
    "C2": [1, 1, 5, 1, 2, 1]
})

# 生成每个行对应的Group分组下C1的均值,结果和原df长度一致
c1_group_mean = df.groupby("Group")["C1"].transform("mean")
# 直接用布尔索引筛选
filtered_df = df[df["C1"] >= c1_group_mean]
print(filtered_df)

输出结果:

Group  C1  C2
1     A   2   1
2     A   3   5
4     B   3   2
5     C   1   1

示例2:筛选C2列值≤分组均值的行

只需要替换列名和比较运算符,逻辑完全一致:

c2_group_mean = df.groupby("Group")["C2"].transform("mean")
filtered_df = df[df["C2"] <= c2_group_mean]
print(filtered_df)

输出结果:

Group  C1  C2
0     A   1   1
1     A   2   1
3     B   2   1
5     C   1   1

为什么这个方法更好?

  • 简洁直观:两行代码搞定,比循环拼接可读性高太多
  • 性能优异:transform是Pandas内置的向量化操作,在大数据集上的速度比Python循环快一个数量级
  • 扩展性强:不仅限于均值,还能轻松替换成其他统计量,比如中位数、分位数,甚至自定义函数。比如筛选大于分组中位数的行:
    c1_group_median = df.groupby("Group")["C1"].transform("median")
    filtered_df = df[df["C1"] > c1_group_median]
    

关于你尝试的groupby.filter

你之前用filter没成功是因为它的设计目的是筛选整个分组,而不是逐行筛选。filter要求传入的函数返回一个单个布尔值(比如判断整个分组的均值是否大于2),而不是逐行的布尔序列。所以如果要做逐行的条件判断,transform才是正确的工具。

对比R语言的实现

你提到R有简便写法,比如用dplyr的话,写法非常直观:

library(dplyr)

df <- data.frame(
  Group = c("A", "A", "A", "B", "B", "C"),
  C1 = c(1, 2, 3, 2, 3, 1),
  C2 = c(1, 1, 5, 1, 2, 1)
)

# 筛选C1≥分组均值的行
filtered_df <- df %>%
  group_by(Group) %>%
  filter(C1 >= mean(C1)) %>%
  ungroup()

这和Pandas的transform思路本质是一样的,都是在分组上下文里完成逐行的条件判断。

内容的提问来源于stack exchange,提问作者an_drade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:02:25