Pandas向量化实现按小时分组的时间序列滚动均值计算
实现方案
需求说明
现有按整点采集的时间序列数据集,包含两列:
date:datetime64类型时间列values:数值列
每日固定24行,对应当天0点到23点的整点数据。需要新增一列,计算指定时间范围内、同一整点时刻的values滚动均值:- 窗口设为
365*24(全局行计数)时,新列值为过去一整年同个整点时刻的values平均值 - 窗口设为24(全局行计数)时,计算效果参考如下示例:
- 窗口设为
index date(as datetime64) values new_column reasoning 0 2021-02-21 00:00:00+00:00 100 - 1 2021-02-21 01:00:00+00:00 200 - ...(省略首天剩余22行数据) 24 2021-02-22 00:00:00+00:00 200 150 (即两天00:00对应值100和200的均值) 25 2021-02-22 01:00:00+00:00 400 300 (即两天01:00对应值200和400的均值) ...(省略次日剩余行数据)
原有方案的问题
- 直接调用
df.groupby(df.date.dt.hour).values.mean()仅能返回全数据集范围内各小时的全局均值,无法实现滚动窗口逻辑 - 直接链式调用
groupby(df.date.dt.hour).values.rolling(X).mean()存在两个核心问题:- 窗口参数取值错误:分组后每个子集内仅包含同小时的样本,相邻样本间隔为1天,若传入全局窗口大小(如24、365*24)会导致计算范围完全偏离需求
- 返回结果为多层索引,和原DataFrame行顺序、索引不匹配,无法直接赋值为新列
向量化实现代码
计算前首先确保数据集严格按date列升序排列、无缺失整点行,否则会出现滚动计算错位:
import pandas as pd # 1. 按时间升序排序,重置索引保证连续性 df = df.sort_values('date').reset_index(drop=True) # 2. 配置滚动参数:统计过去N天的同小时均值,此处以窗口2天(对应全局行窗口24)为例 roll_days = 2 # 若要算过去一年同小时均值,改为365即可 # 3. 分组滚动计算,处理索引对齐后直接赋值 df['new_column'] = ( df.groupby(df['date'].dt.hour)['values'] .rolling(window=roll_days, min_periods=roll_days) .mean() .reset_index(level=0, drop=True) # 丢弃分组产生的小时层级索引,对齐原表 ) # 4. 如需和示例一致用'-'填充空值(首行凑不满窗口的位置),取消下一行注释即可 # df['new_column'] = df['new_column'].fillna('-')
逻辑说明
- 该实现为pandas原生向量化计算,无Python层循环,性能和原生
rolling接口一致,可支持百万行级数据集快速计算 - 分组后每个子集仅包含同一小时的所有样本,相邻样本间隔为1天,因此窗口大小直接传入要统计的天数即可,无需乘以24
min_periods=roll_days参数保证只有窗口内凑满足够天数的同小时样本才返回计算结果,不足的位置返回空值,和示例首天无历史数据则新列为空的逻辑完全一致- 最终通过
reset_index处理后返回的序列索引和原DataFrame完全对齐,可直接赋值为新列,不会出现索引错位问题
内容的提问来源于stack exchange,提问作者j riv
相关产品推荐
相关产品推荐

