如何在Polars中按日、小时分组执行31天滚动均值计算?
按小时计算过去31天Amount均值的问题分析与解决方案
问题背景
- 数据集包含列:
Node、Time(小时间隔)、date(对应Time的日期)、Hour、Amount,每个Node每小时仅一条数据 - 需求:每日每个Hour,计算该小时过去31天的
Amount均值 - 尝试代码:
df.rolling('Time', period='31d', group_by=['date', 'Hour']).agg(pl.col('Amount').mean())
- 异常:结果行数与原数据集一致,未得到每日每小时一行的预期输出
原代码计算逻辑解析
这段代码的核心问题在于分组逻辑和滚动窗口的匹配错误:
group_by=['date', 'Hour']会将数据拆分为【日期+小时】的分组,但原数据中每个Node每小时一条,所以每个分组实际是【日期+小时+Node】的单条数据- 对单条数据做31天滚动窗口计算,只能得到该条数据自身的均值,最终所有分组结果拼接后,行数自然和原数据完全一致
- 本质是按【日期+小时+Node】的细粒度计算,而非需求的【日期+小时】聚合粒度
正确实现方法
场景1:按每日每小时(合并所有Node)计算过去31天均值
如果需要将同一小时所有Node的Amount先聚合,再计算过去31天均值:
# 1. 先聚合得到每日每小时的总Amount(可根据业务调整聚合方式,比如mean) daily_hourly_agg = df.group_by(['date', 'Hour']).agg( pl.col('Amount').sum().alias('DailyHourlyTotal') ).sort('date') # 确保时间序列有序 # 2. 按Hour分组,做31天滚动窗口均值计算 final_result = daily_hourly_agg.group_by('Hour').rolling( index_column='date', period='31d' ).agg( pl.col('DailyHourlyTotal').mean().alias('Past31dAvg') )
场景2:按每个Node的每日每小时计算过去31天均值
如果需要保留Node维度,计算每个Node下各小时的过去31天均值:
final_result = df.group_by(['Node', 'Hour']).rolling( index_column='date', period='31d' ).agg( pl.col('Amount').mean().alias('Past31dAvg') ).sort(['Node', 'Hour', 'date'])
逻辑说明
- 先按
Hour(或Node+Hour)分组,确保每个分组内是同一小时(或同一Node+小时)的全日期数据 - 基于
date列做31天滚动窗口,计算窗口内Amount的均值,最终结果即为每日每小时(或Node+每日每小时)一行的结构
内容的提问来源于stack exchange,提问作者EtienneT
相关产品推荐
相关产品推荐

