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

使用Pandas删除id分组内首次出现success=Y后的多余行

实现方案

核心逻辑:先按id分组,截取每组从第一行到**首次出现success == 'Y'的行(包含该行)**的所有记录,若组内无success == 'Y'的记录则保留全部行。处理前需先按id、year排序,避免行顺序错乱导致截取错误。


方案1:直观易读版(适合中小数据量)

用分组自定义函数实现,逻辑清晰方便排查问题:

import pandas as pd

# 先按id、年份排序,保证行顺序符合时间逻辑
df = df.sort_values(by=['id', 'year']).reset_index(drop=True)

def filter_post_y_rows(group):
    # 定位组内所有success为Y的行索引
    y_row_index = group.index[group['success'] == 'Y']
    if len(y_row_index) == 0:
        # 组内无Y记录,返回全部行
        return group
    # 有Y记录时,截断到第一个Y所在的行(包含该行)
    return group.loc[:y_row_index[0]]

# 分组应用过滤逻辑
result_df = df.groupby('id', group_keys=False).apply(filter_post_y_rows).reset_index(drop=True)

方案2:高性能向量化版(适合大数据量)

基于pandas内置的累计运算实现,无逐组循环,处理百万行以上数据时速度优势明显:

import pandas as pd

# 先按id、年份排序
df = df.sort_values(by=['id', 'year']).reset_index(drop=True)

# 标记Y行,计算组内累计是否已出现Y
df['is_y'] = df['success'].eq('Y')
df['has_y_before'] = df.groupby('id')['is_y'].cummax()
# 错位标记首次Y之后的行:错位后为True的行就是需要删除的行
df['drop_flag'] = df.groupby('id')['has_y_before'].shift(fill_value=False)
# 过滤掉需要删除的行,清理临时列
result_df = df[~df['drop_flag']].drop(columns=['is_y', 'has_y_before', 'drop_flag']).reset_index(drop=True)

效果验证

两种方案运行后输出结果完全匹配预期:

  • id==1组截断到2002年首次出现Y的行,删除2003、2004年的后续记录
  • id==2组无Y记录,保留全部3行
  • id==3组Y出现在组内最后一行,无多余行需要删除,保留全部记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:57:21