如何为带时间戳的DataFrame设置自定义步长的滚动窗口?
按整日历日步进的多日窗口处理方案
你的核心需求是:窗口包含连续N个完整日历日的所有小时数据,且窗口按整日历日步进(而非小时级滑动),pandas.DataFrame.rolling的默认时间窗口是滑动式的,确实不直接适配,但不需要完全自定义窗口函数,以下两种方案可以解决:
方案1:手动生成窗口边界,按需筛选计算
这种方式灵活性最高,适合需要保留小时级原始数据的场景:
- 提取时间列的日期部分,获取所有唯一日历日
- 遍历生成每个N天窗口的起始/结束日期
- 筛选对应日期范围的数据,执行自定义操作
示例代码(以2天窗口为例):
import pandas as pd # 假设你的DataFrame是df,复合索引为(time, node) df = df.reset_index() # 将索引转为列,方便日期筛选 # 获取所有唯一的日历日 unique_days = df['time'].dt.date.unique() window_output = [] # 遍历生成每个2天窗口 for idx in range(len(unique_days) - 1): start_day = unique_days[idx] end_day = unique_days[idx + 1] # 筛选窗口内的所有小时数据:从start_day 00:00到end_day 23:59 window_mask = (df['time'].dt.date >= start_day) & (df['time'].dt.date <= end_day) window_df = df[window_mask] # 这里替换为你的实际操作,比如按node计算统计值 node_stats = window_df.groupby('node').agg( avg_value=('value', 'mean'), total_count=('value', 'count') ) # 给结果添加窗口标识 node_stats['window_start'] = pd.Timestamp(start_day) node_stats['window_end'] = pd.Timestamp(end_day) + pd.Timedelta(hours=23, minutes=59, seconds=59) window_output.append(node_stats) # 合并所有窗口结果 final_result = pd.concat(window_output).reset_index()
方案2:结合resample与rolling实现
如果你的操作可以先按天聚合,再滑动窗口,这种写法更简洁:
# 先将数据按node和天分组,计算每日聚合值(根据需求调整聚合逻辑) daily_agg = df.reset_index().groupby( ['node', pd.Grouper(key='time', freq='D')] ).agg(total_value=('value', 'sum')).reset_index() # 对每个node,使用rolling(window=2)实现2天滑动窗口计算 sliding_result = daily_agg.groupby('node').rolling( window=2, on='time' ).agg(rolling_total=('total_value', 'sum')).reset_index()
总结
两种方案都无需完全自定义窗口函数:
- 方案1适合需要保留小时级细节、执行复杂窗口操作的场景
- 方案2适合先按天聚合再滑动的场景,代码更简洁
内容的提问来源于stack exchange,提问作者abscond
相关产品推荐
相关产品推荐

