基本上,我想计算一个常数的幂的总和。
举例来说:
import polars as pl c = 2 df = pl.DataFrame({"a": [1, 2, 3]}) df.select(pl.lit(c).pow(pl.col("a")).sum()) shape: (1, 1) ┌─────────┐ │ literal │ │ --- │ │ i32 │ ╞═════════╡ │ 14 │ └─────────┘
但是,当我尝试在 groupby agg 上下文中执行同样的事情时,出现错误:
import polars as pl c = 2 df = pl.DataFrame({"a": [1, 2, 3, 1, 2, 3], "b": [1, 1, 1, 2, 2, 2]}) df.group_by("b").agg(pl.lit(c).pow(pl.col("a")).sum()) # Error originated in expression: '2i32.pow([col("a")])'
我可以让它工作的一个(临时)方法是预先在 df 上附加一个列,例如
df = df.with_columns(pl.lit(c).alias("c"))
但它并不干净,因为原始 df 中可能有一个名为“c”(或我给出的任何别名)的现有列,这可能会导致列名冲突。
我确信一定有更好更干净的方法来实现这一点。但是怎么做呢?
更新:旧的行为是一个错误。文字现在可以按预期广播。
df.group_by("b").agg(pl.lit(c).pow(pl.col("a")).sum()) shape: (2, 2) ┌─────┬─────────┐ │ b ┆ literal │ │ --- ┆ --- │ │ i64 ┆ i32 │ ╞═════╪═════════╡ │ 1 ┆ 14 │ │ 2 ┆ 14 │ └─────┴─────────┘
看起来您可能需要.repeat_by使长度匹配。
.repeat_by
df.group_by("b").agg( pl.lit(c).repeat_by("a").pow(pl.col("a")).sum() ) shape: (2, 2) ┌─────┬─────────┐ │ b ┆ literal │ │ --- ┆ --- │ │ i64 ┆ f64 │ ╞═════╪═════════╡ │ 1 ┆ 14.0 │ │ 2 ┆ 14.0 │ └─────┴─────────┘
感谢更新和分享新的解决方案!从您提供的代码来看,新的行为修复了之前的问题,并且.repeat_by()提供了一种优雅的方法来处理长度匹配的问题。
.repeat_by()
使用.repeat_by("a")对常量c进行扩展,然后与列进行幂次运算并求和:
.repeat_by("a")
c
df.group_by("b").agg( pl.lit(c).repeat_by("a").pow(pl.col("a")).sum() )
输出结果如预期地对分组后的b列求得了正确的总和。
b
输出表明,每个组中的值被正确计算并累加:
┌─────┬─────────┐ │ b ┆ literal │ │ --- ┆ --- │ │ i64 ┆ f64 │ ╞═════╪═════════╡ │ 1 ┆ 14.0 │ │ 2 ┆ 14.0 │ └─────┴─────────┘
这是因为c的值被正确扩展和广播,并与列a一起进行了幂运算。
a
这个解决方案展示了如何利用Polars的.repeat_by()方法优雅地解决分组聚合中的广播问题。如果您有更多类似的操作场景,这种方法或许能够成为标准的处理方式! 🚀