Pandas时间序列处理:如何展开日期区间并添加0-2天滞后特征
实现步骤
整体逻辑分3步:日期格式转换、日期区间逐行展开、按规则生成滞后特征。
1. 前置数据格式修正
先把字符串类型的日期转成pandas可计算的datetime格式,把字符串类型的特征转成数值类型,避免后续计算报错:
import pandas as pd import numpy as np # 加载测试用DataFrame df = pd.DataFrame( { "start_date": [ "2020-01-01", "2020-01-05", "2020-01-01", "2020-01-06", ], "end_date": [ "2020-01-02", "2020-01-07", "2020-01-02", "2020-01-07" ], "id": ["1", "1", "3", "3"], "feature1": ["111", "111", "333", "555"], "feature2": ["222", "222", "444", "666"], } ) # 日期转datetime格式 df['start_date'] = pd.to_datetime(df['start_date']) df['end_date'] = pd.to_datetime(df['end_date']) # 特征转数值格式 df['feature1'] = pd.to_numeric(df['feature1']) df['feature2'] = pd.to_numeric(df['feature2'])
2. 日期区间展开
每个投放区间的覆盖范围不是原有的start_date ~ end_date,而是向后额外延伸2天(用来存放滞后特征的尾部值),生成连续日期序列后炸开成独立行:
# 生成连续日期范围:从start_date开始,到end_date+2天为止的每日序列 df['date_range'] = df.apply( lambda row: pd.date_range( start=row['start_date'], end=row['end_date'] + pd.Timedelta(days=2), freq='D' ), axis=1 ) # 炸开日期序列成独立行,保留end_date字段用于后续滞后判断 expanded_df = df.explode('date_range')[ ['id', 'date_range', 'end_date', 'feature1', 'feature2'] ].rename(columns={'date_range': 'date'})
3. 生成0-2阶滞后特征
滞后规则和目标输出完全匹配:
- 对于滞后阶数
k(k=0/1/2),只要当前展开的date≤ 原区间end_date + k天,就取原特征值,否则置为NaN
lag_steps = [0, 1, 2] for k in lag_steps: # 计算每个滞后阶数的取值阈值 threshold = expanded_df['end_date'] + pd.Timedelta(days=k) # 按条件赋值 expanded_df[f'f1_lag_{k}'] = np.where( expanded_df['date'] <= threshold, expanded_df['feature1'], np.nan ) expanded_df[f'f2_lag_{k}'] = np.where( expanded_df['date'] <= threshold, expanded_df['feature2'], np.nan ) # 整理成目标列顺序,移除中间计算用的临时字段 target_cols = ['date', 'id', 'f1_lag_0', 'f2_lag_0', 'f1_lag_1', 'f2_lag_1', 'f1_lag_2', 'f2_lag_2'] result = expanded_df[target_cols].reset_index(drop=True)
结果说明
跑通代码后输出的result和要求的目标格式完全一致,不存在跨投放块的特征串值问题,所有NaN位置、特征取值都和示例匹配。
注意:如果后续需要扩展更多滞后阶数(比如0~3天的滞后),只需要修改
lag_steps列表的取值即可,不需要调整其他逻辑。
内容的提问来源于stack exchange,提问作者Vega
相关产品推荐
相关产品推荐

