如何为含小时值的Pandas DataFrame计算带日周期性的5小时滚动平均值?
周期性5小时滚动平均的实现方法
针对这种24小时周期的滚动平均需求,核心思路是为每个ID的时间序列补充首尾的周期数据,让常规滚动窗口能覆盖跨0点/23点的情况,具体实现如下:
实现步骤
- 按
ID分组,对每个分组单独处理:- 提取分组末尾2小时(hour=22、23)和开头2小时(hour=0、1)的数据
- 将末尾2小时数据拼到原序列开头,开头2小时数据拼到原序列结尾,得到扩展后的序列
- 对扩展序列计算窗口为5、
center=True的滚动平均值 - 截取扩展序列中间的24行,对应原有的0-23小时,即为每个ID的周期性滚动平均结果
代码示例
import numpy as np import pandas as pd # 构造原DataFrame(与题目代码一致) ids = ['a', 'b', 'c'] hours = np.arange(24) data = np.random.random((len(ids), len(hours))) df = pd.concat([pd.DataFrame(index=[[id]*len(hours), hours], data={'value': data[ind]}) for ind, id in enumerate(ids)]) df.index.names = ['ID', 'hour'] # 定义处理单个ID分组的函数 def periodic_rolling_mean(group): # 提取首尾需要补充的周期数据 tail_data = group.tail(2) head_data = group.head(2) # 拼接得到扩展序列 extended_data = pd.concat([tail_data, group, head_data]) # 计算滚动平均值 extended_data['rolling_mean'] = extended_data['value'].rolling(5, center=True).mean() # 截取对应原24小时的结果 return extended_data.iloc[2:-2].copy() # 分组应用并合并结果 df_result = df.groupby('ID').apply(periodic_rolling_mean).reset_index(level=0, drop=True)
逻辑说明
扩展后的序列长度为28(24+4),使用rolling(5, center=True)时:
- 原序列的0点对应扩展序列的第2个位置,窗口包含扩展序列前5行(22、23、0、1、2点)
- 原序列的23点对应扩展序列的第25个位置,窗口包含扩展序列最后5行(21、22、23、0、1点)
完美匹配周期性滚动平均的需求。
内容的提问来源于stack exchange,提问作者hm8
相关产品推荐
相关产品推荐

