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

如何用Polars原生表达式实现跨DataFrame的区间过滤与聚合?

Polars原生表达式实现区间值求和

核心思路

抛弃逐行迭代的map_rows,改用Polars原生向量化表达式API,利用引擎的批量处理能力提升性能。以下提供两种适用不同场景的方案:


方案一:向量化广播匹配(中小数据量)

直接通过广播比较实现区间匹配,再求和,代码简洁且高效:

import polars as pl

# 示例数据
df1 = pl.DataFrame({
    "start": [1, 5, 9],
    "end": [4, 8, 12]
})

df2 = pl.DataFrame({
    "idx": [2, 3, 6, 7, 10, 11],
    "values": [10, 20, 30, 40, 50, 60]
})

# 生成结果
result = df1.with_columns(
    sum_values=pl.sum(
        pl.when((df2["idx"] >= pl.col("start")) & (df2["idx"] <= pl.col("end")))
        .then(df2["values"])
        .otherwise(0)
    )
)

print(result)

输出结果:

shape: (3, 3)
┌───────┬─────┬────────────┐
│ start ┆ end ┆ sum_values │
│ ---   ┆ --- ┆ ---        │
│ i64   ┆ i64 ┆ i64        │
╞═══════╪═════╪════════════╡
│ 1     ┆ 4   ┆ 30         │
│ 5     ┆ 8   ┆ 70         │
│ 9     ┆ 12  ┆ 110        │
└───────┴─────┴────────────┘

方案二:二分查找+前缀和(大数据量)

当df2数据量极大时,广播会占用过多内存,此时先对df2排序并计算前缀和,再通过二分查找定位区间边界,用前缀和差值得到求和结果,内存占用更低:

# 先对df2按idx排序并计算前缀和
df2_sorted = df2.sort("idx").with_columns(cumsum=pl.col("values").cumsum())

result = df1.with_columns(
    # 定位区间左右边界的位置
    start_pos=pl.col("start").search_sorted(df2_sorted["idx"], side="left"),
    end_pos=pl.col("end").search_sorted(df2_sorted["idx"], side="right")
).with_columns(
    # 通过前缀和差值计算区间和
    sum_values=pl.when(pl.col("end_pos") > 0)
    .then(df2_sorted["cumsum"][pl.col("end_pos")-1])
    .otherwise(0) - pl.when(pl.col("start_pos") > 0)
    .then(df2_sorted["cumsum"][pl.col("start_pos")-1])
    .otherwise(0)
).drop("start_pos", "end_pos")

print(result)

性能优势说明

  • map_rows是Python级别的逐行迭代,每一行都要单独执行查询,性能瓶颈明显。
  • 原生表达式API利用Polars的向量化引擎,一次性完成所有行的条件判断与计算,避免了循环开销,性能提升数倍至数十倍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:54:58