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

如何按ID分组筛选DataFrame行至指定列值≤25?

问题与解决方案

原始数据

import pandas as pd
df = pd.DataFrame({
    'id': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2],
    'value2': [30, 28, 27, 24, 25, 29, 28, 28, 26, 25],
    'value3': [29, 29, 27, 25, 24, 27, 27, 26, 26, 26],
    'value4': [30, 29, 25, 25, 25, 29, 28, 28, 25, 26]
})

对应表格:

idvalue2value3value4
1302930
1282929
1272725
1242525
1252425
2292729
2282728
2282628
2262625
2252626

需求

按id分组,每组筛选所有行直到value2、value3或value4任意一列的值≤25(包含该行),后续行全部剔除。

之前尝试的问题

之前的代码df[df['value2'].eq(25).cummin() | df['value3'].eq(25).cummin() | df['value4'].eq(25).cummin()]存在两个问题:

  • 仅匹配等于25的值,未覆盖≤25的情况
  • 没有按id分组处理,会跨id生效

最优解决方案

通过分组后计算触发条件+累积掩码实现,步骤如下:

完整代码

import pandas as pd

df = pd.DataFrame({
    'id': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2],
    'value2': [30, 28, 27, 24, 25, 29, 28, 28, 26, 25],
    'value3': [29, 29, 27, 25, 24, 27, 27, 26, 26, 26],
    'value4': [30, 29, 25, 25, 25, 29, 28, 28, 25, 26]
})

# 1. 标记每行是否满足任意列≤25的触发条件
df['trigger'] = df[['value2', 'value3', 'value4']].le(25).any(axis=1)

# 2. 按id分组生成筛选掩码:保留从开头到第一次触发的所有行
mask = df.groupby('id')['trigger'].transform(lambda x: ~x.cummax().shift(1, fill_value=False))

# 3. 筛选数据并删除临时列
result = df[mask].drop('trigger', axis=1)

print(result)

代码解释

  • df[['value2', 'value3', 'value4']].le(25).any(axis=1):逐行判断是否有任意一列≤25,生成布尔触发列
  • x.cummax():分组内第一次触发后,后续所有行标记为True
  • shift(1, fill_value=False):将触发标记后移一行,确保触发行本身被保留
  • 取反后得到的掩码,会保留每组从开头到第一次触发的所有行

输出结果

idvalue2value3value4
1302930
1282929
1272725
2292729
2282728
2282628
2262625

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 05:05:44