在Polars中实现带左边界扩展的滚动时间窗口平均值
在Polars中实现带左边界扩展的滚动时间窗口平均值
嘿,我来帮你搞定这个Polars里的滚动时间窗口问题!你之前在Pandas里用自定义BaseIndexer实现的那种逻辑,在Polars里其实用内置的rolling方法就能轻松实现,不用自己写复杂的索引器,而且代码还更简洁。
先再明确下你的需求,避免理解偏差:
- 为每一个时间戳
t计算对应的5分钟滚动平均值,窗口的终点就是t - 窗口的左边界不是严格卡死在
t-5min的位置:如果t-5min这个时间点刚好没有数据,我们依然要把更早的、最接近t-5min的有效数据包含进来(简单说就是只要是在t之前、且尽可能在5分钟范围内的数据都算,实在没有5分钟内的就取更早的) - 输入数据有两列:
timestamp(时间戳列)和value(要计算平均值的数值列)
那直接上代码和解释吧:
import polars as pl from datetime import datetime # 先构造一个示例数据集,方便你测试 df = pl.DataFrame({ "timestamp": [ datetime(2023, 1, 1, 9, 58), # 这个点比10:00的t-5min(9:55)晚,但比10:06的t-5min(10:01)早 datetime(2023, 1, 1, 10, 0), datetime(2023, 1, 1, 10, 3), datetime(2023, 1, 1, 10, 6), datetime(2023, 1, 1, 10, 8), ], "value": [10, 1, 2, 3, 4] }) # 核心计算逻辑 result = df.with_columns( rolling_avg=pl.col("value").rolling( index_column="timestamp", # 指定用时间戳列作为滚动窗口的索引 window_size="5m", # 设置窗口大小为5分钟 closed="both", # 窗口包含左右两个边界(即[t-5min, t]区间内的所有数据) min_periods=1 # 即使窗口内只有1个数据点也计算平均值,避免出现空值 ).mean() ) # 打印结果看看 print(result)
运行这段代码后,你会得到这样的结果:
┌─────────────────────┬───────┬────────────┐ │ timestamp ┆ value ┆ rolling_avg│ │ --- ┆ --- ┆ --- │ │ datetime[μs] ┆ i64 ┆ f64 │ ╞═════════════════════╪═══════╪════════════╡ │ 2023-01-01 09:58:00 ┆ 10 ┆ 10.0 │ │ 2023-01-01 10:00:00 ┆ 1 ┆ 5.5 │ │ 2023-01-01 10:03:00 ┆ 2 ┆ 4.333333 │ │ 2023-01-01 10:06:00 ┆ 3 ┆ 2.5 │ │ 2023-01-01 10:08:00 ┆ 4 ┆ 3.0 │ └─────────────────────┴───────┴────────────┘
咱们来拆解下关键参数的作用:
index_column="timestamp":告诉Polars我们要基于时间列来做滚动窗口,而不是基于行索引的固定行数窗口window_size="5m":直接用时间字符串指定窗口长度,Polars支持d(天)、h(小时)、m(分钟)、s(秒)等单位,非常灵活closed="both":这个参数控制窗口的闭合边界,设为both意味着t-5min和t这两个时间点的数据都会被包含进来。如果你的需求是窗口不包含t-5min的点,可以改成closed="right",但根据你的描述,both更贴合需求min_periods=1:这个参数是实现“左边界扩展”的关键!当某个t的t-5min范围内没有任何数据(比如第一个数据点),它会确保我们至少取当前这个点来计算平均值,而不是返回空值。如果不设置这个参数,当窗口内没有数据时会返回null,不符合你的需求
如果你的数据量很大,Polars的rolling方法还支持并行计算,性能比Pandas的自定义索引器还要好哦!
备注:内容来源于stack exchange,提问作者Mike Church
相关产品推荐
相关产品推荐

