Pandas:按组查找指定类别最后出现位置并过滤行
按分组保留指定Sender最后出现位置后的所有记录
实现思路
针对每个id分组,完成两个核心操作:
- 若组内存在目标Sender(如
bot),定位其最后一次出现的行索引,保留该索引及之后的所有行 - 若组内无目标Sender,直接保留整个组的所有行
代码实现
1. 初始化数据
import pandas as pd data = [[1,'bot', 'a'], [1,'cust', 'b'], [1,'bot', 'c'],[1,'cust', 'd'],[1,'agent', 'e'],[1,'cust', 'f'], [2,'bot', 'a'],[2,'cust', 'b'],[2,'bot', 'c'],[2,'bot', 'd'],[2,'agent', 'e'],[2,'cust', 'f'],[2,'agent', 'g'], [3,'cust', 'h'],[3,'cust', 'i'],[3,'agent', 'k'],[3,'agent', 'l']] df = pd.DataFrame(data, columns=['id', 'sender','text'])
2. 简洁实现方案
利用groupby+transform快速标记每个组的保留起始位置:
target_sender = 'bot' # 给每行标记所在组的目标Sender最后出现位置,无目标则取组起始位置 df['keep_start_idx'] = df.groupby('id')['sender'].transform( lambda x: x[x == target_sender].index[-1] if (x == target_sender).any() else x.index[0] ) # 筛选出起始位置及之后的行,清理临时列 result_df = df[df.index >= df['keep_start_idx']].drop('keep_start_idx', axis=1) print(result_df)
3. 分步实现方案(更易理解)
如果需要更清晰的步骤拆分,可以用以下方式:
target_sender = 'bot' # 提取所有组中目标Sender最后一次出现的索引 last_target_indices = df[df['sender'] == target_sender].groupby('id').tail(1).index keep_indices = [] # 遍历每个分组,收集需要保留的行索引 for group_id in df['id'].unique(): group = df[df['id'] == group_id] if group_id in df[df['sender'] == target_sender]['id'].unique(): # 获取当前组最后一个目标Sender的索引 last_idx = last_target_indices[last_target_indices.isin(group.index)][0] # 收集该索引及之后的所有行索引 keep_indices.extend(group[group.index >= last_idx].index.tolist()) else: # 无目标Sender,保留整个组 keep_indices.extend(group.index.tolist()) # 生成结果DataFrame result_df = df.loc[keep_indices] print(result_df)
输出结果
最终输出会按要求保留每组目标Sender最后出现后的所有记录:
id sender text 2 1 bot c 3 1 cust d 4 1 agent e 5 1 cust f 3 2 bot d 4 2 agent e 5 2 cust f 6 2 agent g 7 3 cust h 8 3 cust i 9 3 agent k 10 3 agent l
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

