基于多条件分组过滤DataFrame:满足条件后移除后续行
问题解决:按ID截断Payment Done成功后的后续行
问题背景
原始DataFrame:
ID Activity Action No. Status A1 register 1 in A1 fill form 2 in A2 Payment Done 3 success A2 fill form 2 in B1 fill form 1 in B1 Payment Done 2 success B1 Process_drop 3 in B1 fill form 1 in
预期得到的DataFrame:
ID Activity Action No. Status A1 register 1 in A1 fill form 2 in A2 Payment Done 3 success B1 Payment Done 2 success
需求:对每个ID,一旦出现Activity == 'Payment Done'且Status == 'success'的行,就删除该ID在这行之后的所有记录。
解决方案
用Pandas的分组和累积判断就能实现,直接看步骤和代码:
实现步骤
- 给每行打标记,判断是否是触发截断的目标行;
- 按ID分组,用累积最大值(
cummax())追踪是否已经出现过触发行——只要出现过一次,后续所有行的标记都会变成True; - 筛选出触发行及之前的所有记录,最后清理辅助列。
完整代码
import pandas as pd # 构造原始数据(如果已有现成DataFrame,可跳过此步骤) data = { 'ID': ['A1', 'A1', 'A2', 'A2', 'B1', 'B1', 'B1', 'B1'], 'Activity': ['register', 'fill form', 'Payment Done', 'fill form', 'fill form', 'Payment Done', 'Process_drop', 'fill form'], 'Action No.': [1, 2, 3, 2, 1, 2, 3, 1], 'Status': ['in', 'in', 'success', 'in', 'in', 'success', 'in', 'in'] } df = pd.DataFrame(data) # 标记触发截断的行 df['trigger'] = (df['Activity'] == 'Payment Done') & (df['Status'] == 'success') # 按ID计算:保留触发行及之前的所有记录 df['keep'] = df.groupby('ID')['trigger'].transform(lambda x: ~x.cummax() | x) # 筛选结果并删除辅助列 result_df = df[df['keep']].drop(columns=['trigger', 'keep']) print(result_df)
代码解释
cummax()在分组内从前往后遍历,只要碰到一次True(触发行),后面所有行的这个值都会保持True,相当于标记“已经过了截断点”;~x.cummax()保留截断点之前的行,|x把触发行本身也包含进来,刚好得到我们需要的结果。
内容的提问来源于stack exchange,提问作者Roshankumar
相关产品推荐
相关产品推荐

