如何用步长1、大小2的滚动前向窗口构建多变量时间序列DataFrame
问题描述
给定如下示例DataFrame:
import pandas as pd import numpy as np timestamps = pd.date_range(start='2017-01-01', end='2017-01-5', inclusive='left') values = np.arange(0,len(timestamps)) df = pd.DataFrame({'A': values ,'B' : values*2}, index = timestamps ) print(df)
输出的原始数据:
A B 2017-01-01 0 0 2017-01-02 1 2 2017-01-03 2 4 2017-01-04 3 6
需要实现窗口大小为2、步长为1的滚动前向采样,生成如下格式的结果:
timestep_1 timestep_2 target 0 A 0 1 2 B 0 2 4 1 A 1 2 3 B 2 4 6
每个窗口对应一组数据,包含窗口内A、B的两个值,以及窗口右侧紧邻的A、B值作为target。尝试过pandas的rolling方法,但该方法需结合聚合函数,无法直接满足需求,寻求可行实现方案。
解决方案
可以通过滑动窗口提取+数据重组的方式实现,以下是两种高效简洁的方法:
方法一:利用shift与列重组
通过位移操作直接拼接窗口特征与目标值,再调整索引结构匹配需求:
import pandas as pd import numpy as np # 生成原始DataFrame timestamps = pd.date_range(start='2017-01-01', end='2017-01-5', inclusive='left') values = np.arange(0,len(timestamps)) df = pd.DataFrame({'A': values ,'B' : values*2}, index = timestamps ) window_size = 2 # 构造窗口内的timestep列 window_cols = pd.concat( [df.shift(window_size - 1 - i) for i in range(window_size)], axis=1, keys=[f'timestep_{i+1}' for i in range(window_size)] ) # 提取窗口右侧的target值 target_col = df.shift(-1).rename(columns=lambda x: 'target') # 合并数据并过滤无效行 result = pd.concat([window_cols, target_col], axis=1).dropna() # 调整索引为目标层级结构 result = result.stack(level=0).swaplevel(0, 1).sort_index() result.index.names = [None, None] print(result)
输出结果:
timestep_1 timestep_2 target 0 A 0.0 1.0 2.0 B 0.0 2.0 4.0 1 A 1.0 2.0 3.0 B 2.0 4.0 6.0
方法二:利用numpy滑动窗口批量处理
针对大规模数据,使用numpy的滑动窗口可以提升处理效率:
import pandas as pd import numpy as np # 生成原始DataFrame timestamps = pd.date_range(start='2017-01-01', end='2017-01-5', inclusive='left') values = np.arange(0,len(timestamps)) df = pd.DataFrame({'A': values ,'B' : values*2}, index = timestamps ) window_size = 2 n_windows = len(df) - window_size # 批量提取窗口数据(形状:n_windows × window_size × 列数) window_data = np.lib.stride_tricks.sliding_window_view(df.values, window_size, axis=0) # 提取每个窗口对应的target值 target_data = df.values[window_size:] # 重组为目标格式 result_rows = [] for window_idx in range(n_windows): for col_name, win_vals, target_val in zip(df.columns, window_data[window_idx].T, target_data[window_idx]): result_rows.append([window_idx, col_name, win_vals[0], win_vals[1], target_val]) result = pd.DataFrame( result_rows, columns=['', '', 'timestep_1', 'timestep_2', 'target'] ).set_index(['', '']).sort_index() print(result)
输出结果与方法一完全一致。
内容的提问来源于stack exchange,提问作者Oblomov
相关产品推荐
相关产品推荐

