如何按组删除某列值变更后回退的所有后续数据行?
分组处理数据集:截断回退至初始值后的行
问题描述
现有如下结构的数据集:
ID Date CD 0 1 1/1/2015 A 1 1 1/2/2015 A 2 1 1/3/2015 A 3 1 1/4/2015 A 4 1 1/5/2015 B 5 1 1/6/2015 B 6 1 1/7/2015 A 7 1 1/8/2015 A 8 1 1/9/2016 C 9 2 1/2/2015 A 10 2 1/3/2015 A 11 2 1/4/2015 A 12 2 1/5/2015 A 13 2 1/6/2015 A 14 2 1/7/2015 A
需求:按ID分组,当CD列的值从初始值发生变更后又回退至初始值时,删除回退起始行及之后的所有行。例如ID=1的组中,CD从A变为B后又变回A,需删除行6、7、8,最终保留至行5。
解决方案
使用Pandas的分组功能结合自定义处理函数实现需求,代码如下:
import pandas as pd # 构造示例数据集 data = { 'ID': [1,1,1,1,1,1,1,1,1,2,2,2,2,2,2], 'Date': ['1/1/2015','1/2/2015','1/3/2015','1/4/2015','1/5/2015','1/6/2015','1/7/2015','1/8/2015','1/9/2016','1/2/2015','1/3/2015','1/4/2015','1/5/2015','1/6/2015','1/7/2015'], 'CD': ['A','A','A','A','B','B','A','A','C','A','A','A','A','A','A'] } df = pd.DataFrame(data) def process_single_group(group): # 获取当前组的初始CD值 initial_cd = group['CD'].iloc[0] # 检查组内是否出现过非初始值的变更 has_any_change = (group['CD'] != initial_cd).any() if not has_any_change: # 无变更则直接返回原组 return group # 找到第一个发生变更的位置 first_change_idx = group[group['CD'] != initial_cd].index[0] # 截取第一次变更后的所有行 post_change_rows = group.loc[first_change_idx:] # 找到变更后第一次回退到初始值的位置 first_back_to_initial = post_change_rows[post_change_rows['CD'] == initial_cd].index if len(first_back_to_initial) > 0: # 截断到回退起始行的前一行 return group.loc[:first_back_to_initial[0] - 1] else: # 没有回退到初始值则返回原组 return group # 应用分组处理 processed_df = df.groupby('ID', group_keys=False).apply(process_single_group) print(processed_df)
代码逻辑说明
- 分组初始化:按
ID分组后,先获取每个组的初始CD值。 - 无变更判断:如果组内所有
CD值都是初始值,直接保留整个组。 - 定位变更点:找到组内第一次出现非初始值的位置,截取该位置之后的所有行。
- 定位回退点:在变更后的行中,找到第一次回到初始值的位置,将组截断到该位置的前一行。
- 无回退处理:如果变更后没有回到初始值,则保留整个组。
运行代码后,输出结果符合需求:
ID Date CD 0 1 1/1/2015 A 1 1 1/2/2015 A 2 1 1/3/2015 A 3 1 1/4/2015 A 4 1 1/5/2015 B 5 1 1/6/2015 B 9 2 1/2/2015 A 10 2 1/3/2015 A 11 2 1/4/2015 A 12 2 1/5/2015 A 13 2 1/6/2015 A 14 2 1/7/2015 A
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

