基于分组的DataFrame过滤:保留最后一个value>500之后的行
Pandas分组过滤解决方案
问题描述
按Id分组后,过滤掉每个分组中最后一个value>500的行之前的所有记录,仅保留该行之后的内容;若分组内无value>500的行,则保留整个分组。
解决方案
以下提供两种实现方式,可根据数据规模选择:
方法一:分组应用自定义函数(直观易懂)
先构造匹配原始数据的示例DataFrame:
import pandas as pd data = { 'Id': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C'], 'action': ['enter', 'enter', 'L-1', 'L-2', 'L-2', 'L-3', 'L-4', 'L-5', 'enter', 'L-1', 'L-2', 'L-3', 'enter', 'L-1', 'L-2'], 'date': ['20/12/2021']*8 + ['25/12/2021']*4 + ['26/12/2021']*3, 'value': [0, 150, 520, 50, 550, 20, 5, 1, 2, 510, 6, 3, 4, 10, 20] } df = pd.DataFrame(data)
编写分组过滤函数并应用:
def filter_group(group): # 筛选当前分组中value>500的行 high_value_rows = group[group['value'] > 500] if high_value_rows.empty: # 无符合条件的行,直接返回整个分组 return group # 获取最后一个高值行的索引 last_high_idx = high_value_rows.index[-1] # 返回该索引之后的所有行 return group.loc[group.index > last_high_idx] # 分组处理并重置索引 result_df = df.groupby('Id', group_keys=False).apply(filter_group).reset_index(drop=True)
方法二:使用transform生成标记列(高效适合大数据)
这种方式避免了apply的循环开销,性能更优:
import pandas as pd # 构造原始DataFrame(同上,可省略重复代码) # ... # 生成标记列,标记需要保留的行 df['keep'] = df.groupby('Id')['value'].transform( lambda x: x.index > (x[x > 500].index[-1] if len(x[x > 500]) > 0 else x.index[0] - 1) ) # 筛选保留行并清理临时列 result_df = df[df['keep']].drop('keep', axis=1).reset_index(drop=True)
结果验证
运行上述代码后,result_df将与期望输出完全一致:
Id action date value 0 A L-3 20/12/2021 20 1 A L-4 20/12/2021 5 2 A L-5 20/12/2021 1 3 B L-2 25/12/2021 6 4 B L-3 25/12/2021 3 5 C enter 26/12/2021 4 6 C L-1 26/12/2021 10 7 C L-2 26/12/2021 20
内容的提问来源于stack exchange,提问作者Roshankumar
相关产品推荐
相关产品推荐

