You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars中实现与Pandas一致的重复时间戳滚动计算结果?

在Polars中复刻Pandas重复时间戳下的滚动求和行为

问题场景

使用Pandas和Polars执行滚动求和操作时,遇到重复时间戳的场景下计算结果不一致:Pandas会为同一时间戳的每行单独计算滚动求和,而Polars默认会对同一时间戳的行做聚合处理,导致同一时间戳的结果完全相同。

Pandas实现及输出

import pandas as pd
import polars as pl

data = {
    "timestamp": [
        "2023-08-04 10:00:00",
        "2023-08-04 10:05:00",
        "2023-08-04 10:10:00",
        "2023-08-04 10:10:00",
        "2023-08-04 10:20:00",
        "2023-08-04 10:20:00",
    ],
    "value": [1, 2, 3, 4, 5, 6],
}

pddf = pd.DataFrame(data)
pddf["timestamp"] = pd.to_datetime(pddf["timestamp"])
pddf.set_index("timestamp", inplace=True)
pddf["rolling_sum"] = pddf["value"].rolling("10min").sum()
print(pddf)

输出:

value  rolling_sum
timestamp                              
2023-08-04 10:00:00      1          1.0
2023-08-04 10:05:00      2          3.0
2023-08-04 10:10:00      3          5.0
2023-08-04 10:10:00      4          9.0
2023-08-04 10:20:00      5          5.0
2023-08-04 10:20:00      6         11.0

Polars默认实现及输出

pldf = (
    pl.DataFrame(data)
    .with_columns(pl.col("timestamp").str.strptime(pl.Datetime))
    .sort("timestamp")
    .with_columns(
        pl.col("value")
        .rolling_sum_by(by="timestamp", window_size="10m")
        .alias("rolling_sum")
    )
)
print(pldf)

输出:

┌─────────────────────┬───────┬─────────────┐
│ timestamp           ┆ value ┆ rolling_sum │
│ ---                 ┆ ---   ┆ ---         │
│ datetime[μs]        ┆ i64   ┆ i64         │
╞═════════════════════╪═══════╪═════════════╡
│ 2023-08-04 10:00:00 ┆ 1     ┆ 1           │
│ 2023-08-04 10:05:00 ┆ 2     ┆ 3           │
│ 2023-08-04 10:10:00 ┆ 3     ┆ 9           │
│ 2023-08-04 10:10:00 ┆ 4     ┆ 9           │
│ 2023-08-04 10:20:00 ┆ 5     ┆ 11          │
│ 2023-08-04 10:20:00 ┆ 6     ┆ 11          │
└─────────────────────┴───────┴─────────────┘

解决方案:让Polars复刻Pandas行为

核心思路是让Polars能够逐行处理重复时间戳,而非先聚合相同时间戳的行。可以通过给重复时间戳添加微小的微秒偏移,确保每行拥有唯一的时间戳,再使用Polars的常规rolling方法计算:

pldf = (
    pl.DataFrame(data)
    .with_columns(pl.col("timestamp").str.strptime(pl.Datetime))
    .sort("timestamp")
    # 添加行号,为重复时间戳生成唯一的微秒偏移
    .with_row_index(name="idx")
    .with_columns(
        (pl.col("timestamp") + pl.duration(microseconds=pl.col("idx"))).alias("unique_ts")
    )
    # 基于唯一时间戳执行滚动求和,窗口范围10分钟
    .with_columns(
        pl.col("value")
        .rolling(
            index_column="unique_ts",
            window_size="10m",
            closed="both"
        )
        .sum()
        .alias("rolling_sum")
    )
    # 清理临时列
    .drop("idx", "unique_ts")
)
print(pldf)

输出结果将与Pandas完全一致:

┌─────────────────────┬───────┬─────────────┐
│ timestamp           ┆ value ┆ rolling_sum │
│ ---                 ┆ ---   ┆ ---         │
│ datetime[μs]        ┆ i64   ┆ i64         │
╞═════════════════════╪═══════╪═════════════╡
│ 2023-08-04 10:00:00 ┆ 1     ┆ 1           │
│ 2023-08-04 10:05:00 ┆ 2     ┆ 3           │
│ 2023-08-04 10:10:00 ┆ 3     ┆ 5           │
│ 2023-08-04 10:10:00 ┆ 4     ┆ 9           │
│ 2023-08-04 10:20:00 ┆ 5     ┆ 5           │
│ 2023-08-04 10:20:00 ┆ 6     ┆ 11          │
└─────────────────────┴───────┴─────────────┘

原理说明

  • Pandas的rolling是逐行计算,窗口包含当前行及之前10分钟内的所有行(包括同一时间戳中排在当前行之前的行)。
  • Polars的rolling_sum_by默认会先对相同by列(即timestamp)的行做聚合,再计算滚动窗口,因此同一时间戳的结果相同。
  • 通过添加微秒偏移生成唯一时间戳后,使用Polars的rolling方法(指定index_column),就能实现和Pandas一致的逐行滚动计算逻辑。

内容的提问来源于stack exchange,提问作者cfang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:05:53