Pandas如何按指定频率聚合记录到非逐行滚动时间窗口?
Pandas 实现带时间步长的重叠滚动窗口(支持不规则时间序列)
问题背景
现有时间序列数据(示例如下),需要按固定时间长度的滚动窗口处理,但Pandas原生rolling函数的step参数不支持时间窗口场景(会抛出NotImplementedError: step is not supported with frequency windows),且groupby无法实现重叠窗口。需求方案需适配不规则时间序列(不依赖时间戳固定频率)。
示例数据
import pandas as pd import numpy as np times = pd.date_range(start=pd.Timestamp.now(), end=pd.Timestamp.now() + pd.Timedelta(minutes=1), periods=61) data = np.arange(61) df = pd.DataFrame({'times': times, 'data': data})
解决方案
方案1:自定义窗口起始点 + 布尔索引筛选
核心思路:手动生成符合时间步长要求的窗口起始序列,对每个起始时间筛选出[起始时间, 起始时间+窗口时长]范围内的数据,完全兼容不规则时间序列,支持任意窗口/步长配置。
# 配置窗口参数 window_duration = pd.Timedelta(seconds=2) # 窗口长度 step_duration = pd.Timedelta(seconds=2) # 滑动步长,可自由调整(支持重叠) # 生成窗口起始时间:从数据最早时间到最晚时间,按步长步进 start_times = pd.date_range( start=df['times'].min(), end=df['times'].max() - window_duration, freq=step_duration ) # 遍历提取每个窗口数据 for start in start_times: end = start + window_duration window_df = df[(df['times'] >= start) & (df['times'] <= end)] print(f"窗口区间: {start} ~ {end}") print(window_df) print("-" * 50)
方案优势
- 完全不依赖时间序列的固定频率,时间戳间隔不规则时仍能正常工作
- 窗口长度和滑动步长可独立设置,支持任意比例的重叠窗口(如步长1秒、窗口2秒实现50%重叠)
- 代码简洁,逻辑清晰,便于调试和扩展
方案2:批量生成窗口标签(关联原始数据)
若需要为每条数据标记其所属的所有重叠窗口,可通过交叉合并+筛选实现,适合需要后续按窗口聚合的场景。
# 配置窗口参数 window_duration = pd.Timedelta(seconds=2) step_duration = pd.Timedelta(seconds=2) # 生成带ID的窗口起止时间 window_info = pd.DataFrame({ 'window_start': pd.date_range( start=df['times'].min(), end=df['times'].max() - window_duration, freq=step_duration ) }).assign( window_id=lambda x: x.index, window_end=lambda x: x['window_start'] + window_duration ) # 交叉合并后筛选符合窗口范围的数据 result = df.merge(window_info, how='cross').query( "times >= window_start and times <= window_end" )[['window_id', 'window_start', 'window_end', 'times', 'data']] # 查看结果 print(result)
适用场景
- 需要将窗口标识与原始数据绑定,方便后续按窗口分组聚合
- 数据量适中时效率较高,数据量过大时建议改用方案1的遍历方式
内容的提问来源于stack exchange,提问作者Ben Farmer
相关产品推荐
相关产品推荐

