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

基于分组内子集过滤DataFrame的高效实现方法问询

问题场景与需求

示例DataFrame:

import pandas as pd
df_example = pd.DataFrame({'name': ['a', 'a', 'a', 'b', 'b', 'b'],
                          'class': [1, 2, 2, 3, 2, 2],
                          'price': [3, 4, 2, 1, 6, 5]})

需求:按name分组,筛选出每个分组中price**大于该分组内class==2子集的最小price**的行。

已尝试的操作及问题

  1. 先排序生成临时表,再用groupby.apply尝试过滤,但未得到正确结果:
df_example.sort_values(['name', 'price'], inplace=True)
df_tem = df_example[df_example['class'] == 2].groupby('name').first()
df_example.groupby('name').apply(lambda key, val: val['price'] > df_tem.loc[key]['price']).reset_index()
  1. 尝试新增smallest列再过滤,但生成的列存在大量NaN值,无法正常筛选:
df_example['smallest '] = df_example[df_example['class'] == 2].groupby('name')['price'].transform('first')

预期结果

每个name分组内class=2的最小price为:

class   price
name        
a   2       2
b   2       5

最终需筛选出分组a中price>2、分组b中price>5的行,输出结果:

pd.DataFrame({'name': ['a', 'a', 'b'],
                          'class': [1, 2, 2],
                          'price': [3, 4, 6]})
解决方案

方法一:用transform直接计算分组内目标最小值(高效推荐)

先通过groupby.transform将每个分组中class=2的最小price广播到全组,再进行筛选:

# 计算每个name分组里class=2的最小price,广播到所有行
df_example['min_class2_price'] = df_example.groupby('name')['price'].transform(
    lambda x: x[df_example.loc[x.index, 'class'] == 2].min()
)

# 筛选符合条件的行,删除临时列
result = df_example[df_example['price'] > df_example['min_class2_price']].drop(columns='min_class2_price')

方法二:提取分组最小值后合并筛选

先单独提取每个分组的目标最小值,再合并到原表进行筛选:

# 提取每个name分组中class=2的最小price
min_price_map = df_example[df_example['class'] == 2].groupby('name')['price'].min().rename('min_class2_price')

# 合并到原表,筛选后删除临时列
result = df_example.merge(min_price_map, on='name')
result = result[result['price'] > result['min_class2_price']].drop(columns='min_class2_price')

方法三:groupby.apply直接处理分组(适合小数据集)

自定义函数处理每个分组,直接返回符合条件的行:

def filter_group(group):
    # 获取当前分组中class=2的最小price
    min_p = group[group['class'] == 2]['price'].min()
    # 返回符合条件的行
    return group[group['price'] > min_p]

result = df_example.groupby('name').apply(filter_group).reset_index(drop=True)

关于之前NaN问题的说明

之前的代码出现NaN,是因为先通过df_example[df_example['class'] == 2]过滤掉了非class=2的行,后续transform只能给这些被保留的行赋值,原表中被过滤的行位置就会填充NaN。正确的做法是在transform的lambda函数内部,针对整个分组的索引去筛选class=2的行,而不是提前过滤原表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:35:11