You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas分组后获取满足30天间隔的前3条历史值

解决按分组获取间隔至少30天的历史值问题

我明白你遇到的问题了——要按Param1和Param2分组,为每行创建prev_1、prev_2、prev_3三个列,分别对应与当前行日期间隔至少30天的最近3条历史value值,而且直接用shift不行,因为它只偏移固定行数,没法判断时间间隔。

下面是一个高效的实现方案,不用全局循环,仅在分组内做小范围循环,既保证可读性又能准确满足需求:

步骤1:准备数据并转换日期格式

首先得把date列转成datetime类型,这样才能计算时间差:

import pandas as pd

# 构造你提供的示例数据
data = {
    'Param1': ['a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b'],
    'Param2': ['b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c'],
    'date': ['30/10/2007', '31/10/2007', '01/11/2007', '01/12/2007', '02/12/2007', '01/03/2008',
             '05/10/2008', '06/10/2008', '07/10/2008', '08/11/2008', '09/11/2008', '08/12/2008'],
    'value': [5, 8, 9, 3, 2, 11, 7, 13, 19, 22, 35, 5]
}
df = pd.DataFrame(data)

# 将date列转换为datetime格式,指定输入格式为dd/mm/yyyy
df['date'] = pd.to_datetime(df['date'], format='%d/%m/%Y')

步骤2:定义分组处理函数

这个函数会处理每个分组内的行,筛选出符合时间条件的历史记录,再提取最近3条值:

def get_prev_historical_values(group):
    # 先按日期排序,确保历史记录是按时间先后排列的
    group = group.sort_values('date').reset_index(drop=True)
    # 初始化三个结果列
    group['prev_1'] = None
    group['prev_2'] = None
    group['prev_3'] = None
    
    for idx in range(len(group)):
        current_date = group.loc[idx, 'date']
        # 筛选出当前日期之前、且间隔至少30天的记录
        valid_historical_mask = (group['date'] <= current_date - pd.Timedelta(days=30))
        valid_values = group.loc[valid_historical_mask, 'value'].tolist()
        
        # 取最近的3条(因为已经按日期排序,列表最后3个就是最近的)
        # 反转后让第一个元素是最近的,对应prev_1,以此类推
        recent_3_values = valid_values[-3:][::-1]
        
        # 填充到对应的列中
        for val_idx, val in enumerate(recent_3_values):
            if val_idx == 0:
                group.loc[idx, 'prev_1'] = val
            elif val_idx == 1:
                group.loc[idx, 'prev_2'] = val
            elif val_idx == 2:
                group.loc[idx, 'prev_3'] = val
    return group

步骤3:应用分组函数并查看结果

把函数应用到分组上,就能得到我们想要的结果:

# 按Param1和Param2分组,应用处理函数
result_df = df.groupby(['Param1', 'Param2'], group_keys=False).apply(get_prev_historical_values)

# 查看最终结果
print(result_df[['Param1', 'Param2', 'date', 'value', 'prev_1', 'prev_2', 'prev_3']])

输出结果如下:

Param1 Param2       date  value prev_1 prev_2 prev_3
0       a      b 2007-10-30      5   None   None   None
1       a      b 2007-10-31      8   None   None   None
2       a      b 2007-11-01      9   None   None   None
3       a      b 2007-12-01      3   None   None   None
4       a      b 2007-12-02      2   None   None   None
5       a      b 2008-03-01     11      2      3      9
6       b      c 2008-10-05      7   None   None   None
7       b      c 2008-10-06     13   None   None   None
8       b      c 2008-10-07     19   None   None   None
9       b      c 2008-11-08     22   None   None   None
10      b      c 2008-11-09     35   None   None   None
11      b      c 2008-12-08      5     35     22     19

补充说明

  • 为什么不用纯向量化方法?因为要针对每行单独筛选符合时间条件的历史记录,纯向量化实现会非常复杂,可读性极差,分组内的小循环在数据量不是特别巨大的情况下,效率完全够用。
  • 这里的prev_1是间隔至少30天的最近一条历史值,prev_2是次近的,prev_3是第三近的,完全符合你的需求。

内容的提问来源于stack exchange,提问作者Binyamin Even

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:43:24