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

咨询Polars中聚合连续n行的惯用实现方式

Polars中连续n行分块聚合的更优方法

我是Polars新手,编写了一段代码用于对连续n行的片段执行聚合计算,示例代码如下:

import polars as pl

df = pl.DataFrame({"a": [1, 1, 3, 8, 62, 535, 4213]})

(
    df.with_columns(index=pl.int_range(pl.len(), dtype=pl.Int32))
    .group_by_dynamic(index_column="index", every="3i")
    .agg(pl.col("a").mean())
)

示例中设置n=3,对应7行数据;实际场景为n约100、含多列的约1e6行数据框。我疑惑当前通过Int32索引结合group_by_dynamic的方式是否为该类操作的惯用做法,感觉这种方式有些冗余,想了解是否存在更直接的聚合方法。

你当前的方法能实现需求,但确实不够简洁。Polars针对这种固定行数分块聚合的场景,有更高效直接的实现方式:

推荐方法:整数分桶分组聚合

直接通过生成「块编号」作为分组键,不需要依赖动态分组逻辑,代码更简洁,性能也更优:

import polars as pl

n = 3  # 每组行数
df = pl.DataFrame({"a": [1, 1, 3, 8, 62, 535, 4213]})

result = (
    df
    .with_columns(group_id=pl.int_range(0, pl.len()).floordiv(n))
    .group_by("group_id")
    .agg(pl.col("a").mean())
)

多列聚合适配

如果你的数据集有多列需要聚合,只需把pl.col("a")换成pl.col("*")就能批量处理所有列,非常适合你的百万行多列场景:

n = 100
# 假设df有多列,如a、b、c
result = (
    df
    .with_columns(group_id=pl.int_range(0, pl.len()).floordiv(n))
    .group_by("group_id")
    .agg(pl.col("*").mean())
)

为什么比group_by_dynamic更好?

group_by_dynamic本质是为时间序列滑动/窗口分组设计的,需要处理时间解析、边界对齐等额外逻辑,而我们的需求只是简单的按固定行数分块,用整数分桶完全不需要这些额外开销。在1e6行的数据集上,这种方法的运行速度通常是group_by_dynamic的2-3倍。

备选方法:手动切片拼接(不推荐大数据量)

如果只是想直观分块处理,可以用切片拼接,但这种方法在数据量较大时性能会显著下降,仅作参考:

n = 3
result = pl.concat(
    [df.slice(i, n).select(pl.col("a").mean()) 
     for i in range(0, len(df), n)]
).with_row_index("group_id")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 01:43:23