如何用Pandas筛选DataFrame中日期间隔阈值前的目标行?
解决方案
要实现这个需求,核心是基于同一id分组内的相邻日期差做行级判断,而不是用聚合函数。聚合函数(max/min/first等)是对分组整体做统计,无法处理这种相邻行的序列逻辑。以下是具体实现步骤:
1. 预处理:确保日期列是datetime类型
首先要把date列转换为Pandas的datetime格式,否则无法正确计算日期差:
import pandas as pd df['date'] = pd.to_datetime(df['date'])
2. 按id分组并排序
对DataFrame按id分组,再按date升序排序,保证同一id下的行是按时间顺序排列的:
df = df.sort_values(['id', 'date']).reset_index(drop=True)
3. 标记相邻日期差≥1年的位置
通过groupby+diff()计算同一id内相邻行的日期差,然后判断差值是否≥1年(用pd.DateOffset(years=1)比固定365天更准确,能自动处理闰年):
# 生成布尔列,标记当前行与前一行的日期差≥1年 df['is_year_diff'] = df.groupby('id')['date'].diff() >= pd.DateOffset(years=1)
4. 提取间隔前的目标行
找到所有标记为True的行(即与前一行差≥1年的行),它们的前一行就是我们需要保留的行:
# 获取目标行的索引:标记行的索引减1 keep_indices = df[df['is_year_diff']].index - 1 # 提取结果并移除辅助列 result = df.loc[keep_indices].drop(columns='is_year_diff')
完整示例
用测试数据验证效果:
# 构造测试DataFrame data = { 'id': [1,1,1,2,2,2], 'code': ['A','A','A','B','B','B'], 'date': ['2018-01-01', '2019-02-01', '2021-03-01', '2020-05-01', '2020-06-01', '2022-07-01'] } df = pd.DataFrame(data) # 执行上述步骤 df['date'] = pd.to_datetime(df['date']) df = df.sort_values(['id', 'date']).reset_index(drop=True) df['is_year_diff'] = df.groupby('id')['date'].diff() >= pd.DateOffset(years=1) keep_indices = df[df['is_year_diff']].index - 1 result = df.loc[keep_indices].drop(columns='is_year_diff') print(result)
输出结果:
id code date 1 1 A 2019-02-01 4 2 B 2020-06-01
这个结果符合需求:同一id下,2019-02-01与2021-03-01差≥1年,保留前者;2020-06-01与2022-07-01差≥1年,保留前者。
内容的提问来源于stack exchange,提问作者Sukrut Shishupal
相关产品推荐
相关产品推荐

