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

如何在Polars中根据条件重置cum_sum(累积和)值

问题描述

我有如下LazyFrame,想要构建一个新的累积和列c_sum_n:

import polars as pl
pl.Config(tbl_rows=20)
df= pl.LazyFrame({
    "a" : [0,1,2,3,4,5,6,7,8,9],
    "b" : [33,35,33,32,33,37,33,29,34,36],
    "c" : [33,35,35,35,35,37,37,37,37,37],
})
df = df.with_columns(pl.when(pl.col('b') == pl.col('c')).then(0).otherwise(1).alias('temp'))
df = df.with_columns(pl.when(pl.col('temp') == 0).then(0).otherwise(pl.col('temp').cum_sum()).alias('c_sum_n'))

当前执行后得到如下输出:

>>> df.collect()
shape: (10, 5)
┌─────┬─────┬─────┬──────┬─────────┐
│ a   ┆ b   ┆ c   ┆ temp ┆ c_sum_n │
│ --- ┆ --- ┆ --- ┆ ---  ┆ ---     │
│ i64 ┆ i64 ┆ i64 ┆ i32  ┆ i32     │
╞═════╪═════╪═════╪══════╪═════════╡
│ 0   ┆ 33  ┆ 33  ┆ 0    ┆ 0       │
│ 1   ┆ 35  ┆ 35  ┆ 0    ┆ 0       │
│ 2   ┆ 33  ┆ 35  ┆ 1    ┆ 1       │
│ 3   ┆ 32  ┆ 35  ┆ 1    ┆ 2       │
│ 4   ┆ 33  ┆ 35  ┆ 1    ┆ 3       │
│ 5   ┆ 37  ┆ 37  ┆ 0    ┆ 0       │
│ 6   ┆ 33  ┆ 37  ┆ 1    ┆ 4       │
│ 7   ┆ 29  ┆ 37  ┆ 1    ┆ 5       │
│ 8   ┆ 34  ┆ 37  ┆ 1    ┆ 6       │
│ 9   ┆ 36  ┆ 37  ┆ 1    ┆ 7       │
└─────┴─────┴─────┴──────┴─────────┘

但我期望的输出是当列b等于列c时,累积和值重置为0并重新开始累加,如下:

>>> df.collect()
shape: (10, 5)
┌─────┬─────┬─────┬──────┬─────────┐
│ a   ┆ b   ┆ c   ┆ temp ┆ c_sum_n │
│ --- ┆ --- ┆ --- ┆ ---  ┆ ---     │
│ i64 ┆ i64 ┆ i64 ┆ i32  ┆ i32     │
╞═════╪═════╪═════╪══════╪═════════╡
│ 0   ┆ 33  ┆ 33  ┆ 0    ┆ 0       │
│ 1   ┆ 35  ┆ 35  ┆ 0    ┆ 0       │
│ 2   ┆ 33  ┆ 35  ┆ 1    ┆ 1       │
│ 3   ┆ 32  ┆ 35  ┆ 1    ┆ 2       │
│ 4   ┆ 33  ┆ 35  ┆ 1    ┆ 3       │
│ 5   ┆ 37  ┆ 37  ┆ 0    ┆ 0       │
│ 6   ┆ 33  ┆ 37  ┆ 1    ┆ 1       │
│ 7   ┆ 29  ┆ 37  ┆ 1    ┆ 2       │
│ 8   ┆ 34  ┆ 37  ┆ 1    ┆ 3       │
│ 9   ┆ 36  ┆ 37  ┆ 1    ┆ 4       │
└─────┴─────┴─────┴──────┴─────────┘

寻求Python Polars或Rust Polars的解决方案。


Python Polars 解决方案

核心思路是通过分组实现累积和的重置:每当b == c时生成新的分组,在每个分组内计算累积和,最后将temp为0的行对应值置为0。

代码实现:

import polars as pl
pl.Config(tbl_rows=20)

df= pl.LazyFrame({
    "a" : [0,1,2,3,4,5,6,7,8,9],
    "b" : [33,35,33,32,33,37,33,29,34,36],
    "c" : [33,35,35,35,35,37,37,37,37,37],
})

df = df.with_columns(
    # 生成temp列
    pl.when(pl.col('b') == pl.col('c')).then(0).otherwise(1).alias('temp'),
    # 生成分组ID:每遇到b==c的行,分组ID递增
    pl.col('b').eq(pl.col('c')).cum_sum().alias('group_id')
).with_columns(
    # 按分组计算累积和,同时将temp为0的行重置为0
    pl.when(pl.col('temp') == 0)
    .then(0)
    .otherwise(pl.col('temp').cum_sum().over('group_id'))
    .alias('c_sum_n')
).drop('group_id')  # 可选:删除中间分组列

print(df.collect())

结果验证

执行代码后输出与期望一致:

shape: (10, 5)
┌─────┬─────┬─────┬──────┬─────────┐
│ a   ┆ b   ┆ c   ┆ temp ┆ c_sum_n │
│ --- ┆ --- ┆ --- ┆ ---  ┆ ---     │
│ i64 ┆ i64 ┆ i64 ┆ i32  ┆ i32     │
╞═════╪═════╪═════╪══════╪═════════╡
│ 0   ┆ 33  ┆ 33  ┆ 0    ┆ 0       │
│ 1   ┆ 35  ┆ 35  ┆ 0    ┆ 0       │
│ 2   ┆ 33  ┆ 35  ┆ 1    ┆ 1       │
│ 3   ┆ 32  ┆ 35  ┆ 1    ┆ 2       │
│ 4   ┆ 33  ┆ 35  ┆ 1    ┆ 3       │
│ 5   ┆ 37  ┆ 37  ┆ 0    ┆ 0       │
│ 6   ┆ 33  ┆ 37  ┆ 1    ┆ 1       │
│ 7   ┆ 29  ┆ 37  ┆ 1    ┆ 2       │
│ 8   ┆ 34  ┆ 37  ┆ 1    ┆ 3       │
│ 9   ┆ 36  ┆ 37  ┆ 1    ┆ 4       │
└─────┴─────┴─────┴──────┴─────────┘

Rust Polars 解决方案

逻辑与Python版本一致,通过生成分组ID后计算组内累积和实现重置:

use polars::prelude::*;

fn main() -> Result<()> {
    let df = LazyFrame::new(vec![
        Series::new("a", &[0,1,2,3,4,5,6,7,8,9]),
        Series::new("b", &[33,35,33,32,33,37,33,29,34,36]),
        Series::new("c", &[33,35,35,35,35,37,37,37,37,37]),
    ])?;

    let df = df
        .with_columns([
            // 生成temp列
            col("b")
                .eq(col("c"))
                .then(lit(0))
                .otherwise(lit(1))
                .alias("temp"),
            // 生成分组ID
            col("b")
                .eq(col("c"))
                .cum_sum(false)
                .alias("group_id"),
        ])
        .with_columns([
            // 组内计算累积和并重置
            col("temp")
                .eq(lit(0))
                .then(lit(0))
                .otherwise(col("temp").cum_sum(false).over([col("group_id")]))
                .alias("c_sum_n"),
        ])
        .drop_columns(["group_id"])?;

    println!("{}", df.collect()?);
    Ok(())
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:04:56