如何用polars::prelude::fold_exprs实现单列纵向累加?
问题背景
Polars中fold_exprs函数原本用于实现多列横向累加行值(每行的多列数值求和),示例代码及输出如下:
let df = df!( "a" => &[1, 2, 3], "b" => &[10, 20, 30], )?; let out = df .lazy() .select([fold_exprs(lit(0), |acc, x| Ok(Some(acc + x)), [col("*")]).alias("sum")]) .collect()?; println!("{}", out);
输出:
shape: (3, 1) ┌─────┐ │ sum │ │ --- │ │ i64 │ ╞═════╡ │ 11 │ │ 22 │ │ 33 │ └─────┘
现需使用fold_exprs对单列col("b")实现纵向累加(每行的值为当前行及之前所有行的总和),预期输出:
shape: (3, 1) ┌─────┐ │ sum │ │ --- │ │ i64 │ ╞═════╡ │ 10 │ │ 30 │ │ 60 │ └─────┘
当前尝试修改目标列后未得到预期结果,代码如下:
let out = df .lazy() .select([fold_exprs(lit(0), |acc, x| Ok(Some(acc + x)), [col("b")]).alias("sum")]) .collect()?;
需修改闭包|acc, x| Ok(Some(acc + x))以实现需求。
解决方案
将闭包修改为对acc + x的结果调用cumsum()方法,实现纵向累积求和:
|acc, x| Ok(Some((acc + x).cumsum()))
完整可运行代码:
let df = df!( "a" => &[1, 2, 3], "b" => &[10, 20, 30], )?; let out = df .lazy() .select([fold_exprs(lit(0), |acc, x| Ok(Some((acc + x).cumsum())), [col("b")]).alias("sum")]) .collect()?; println!("{}", out);
原理说明
- 原闭包
acc + x仅完成了初始值0与b列的逐行相加,结果等价于b列本身,无法实现纵向累加效果。 - 添加
.cumsum()后,会对acc + x的结果执行累积求和逻辑:每行的值自动计算为当前行及之前所有行的总和,完全匹配预期输出。
内容的提问来源于stack exchange,提问作者LenC
相关产品推荐
相关产品推荐

