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

如何在groupby后过滤数据?按性别筛选BMI值的实现方法

解决GroupBy后的组内过滤问题

嘿,我来帮你搞定这个需求!你要按性别分组后删除BMI低于组内0.005分位数的数据,思路方向是对的,但现有代码里有几个小问题需要调整,同时我也会给你更简便的实现方式。

先说说你现有代码的问题

你的Bmi_Quartile函数里,if(X['BMI'] <= z)这一行会报错——因为X['BMI'] <= z返回的是一个布尔Series,不能直接用if判断。而且函数没有返回过滤后的数据,apply执行后只会得到一堆None,达不到过滤的目的。


方法一:用groupby.apply实现自定义过滤

我们可以修改函数,让它返回每个组过滤后的子DataFrame,最后用pd.concat合并所有组的结果:

import pandas as pd

def filter_bmi_by_group(X):
    # 计算当前组的BMI 0.005分位数
    q = X['BMI'].quantile(0.005)
    # 返回BMI大于该分位数的行(即保留符合条件的,删除低于的)
    return X[X['BMI'] > q]

# 应用函数并合并结果
filtered_df = pd.concat(BmiDF.groupby('gender').apply(filter_bmi_by_group))

解释:

  • 每个分组会传入filter_bmi_by_group函数,函数计算该组的分位数后,筛选出BMI高于分位数的行并返回。
  • groupby.apply会返回一个包含所有组结果的对象,用pd.concat可以把它们重新组合成一个完整的DataFrame。

方法二:更简便的transform方法(推荐)

如果只是这种简单的组内阈值过滤,用groupby.transform会更高效简洁,不需要自定义函数也能搞定:

# 计算每个性别组的BMI 0.005分位数,广播到每一行
group_quantile = BmiDF.groupby('gender')['BMI'].transform(lambda x: x.quantile(0.005))
# 直接过滤整个DataFrame
filtered_df = BmiDF[BmiDF['BMI'] > group_quantile]

解释:

  • transform会把每个组的分位数结果广播到该组的每一行,生成一个和原DataFrame长度相同的Series。
  • 直接用这个Series和原BMI列比较,就能筛选出所有符合条件的行,代码更短,执行效率也更高(因为transform内部做了优化)。

验证效果

假设你的BmiDF长这样:

BmiDF = pd.DataFrame({
    'gender': ['M', 'M', 'F', 'F', 'M', 'F'],
    'BMI': [18, 15, 16, 14, 20, 17]
})

运行上面的代码后,会自动删除每个性别组里BMI最低的那0.5%(对应0.005分位数),最终得到过滤后的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:48:42