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

如何在Polars中按分组实现列值正负分别缩放?

优化Polars按分组正负值缩放的实现方式

你的现有实现逻辑是正确的,但可以从可读性和性能两方面进行优化,尤其是避免在when/then中重复执行filter操作(大数据量下会增加计算开销)。以下是两种更规范的实现方式:

方式一:提前计算分组内的正负总和(推荐)

先通过窗口函数计算每个分组内的正值总和、负值总和,再基于这两个值进行缩放计算,代码逻辑更直观,且只需要一次分组统计:

import polars as pl

df = pl.DataFrame(
    {
        "foo": [1, 3, -2, -1, 1, 2],
        "bar": [1, 1, 1, 1, 2, 2],
    }
)

result = df.with_columns(
    # 计算分组内的正值总和(仅汇总foo>0的部分)
    pos_sum=pl.col("foo").filter(pl.col("foo") > 0).sum().over("bar"),
    # 计算分组内的负值总和(仅汇总foo<0的部分)
    neg_sum=pl.col("foo").filter(pl.col("foo") < 0).sum().over("bar")
).with_columns(
    foo2=pl.when(pl.col("foo") < 0)
          .then(pl.col("foo") / pl.col("neg_sum"))
          .otherwise(pl.col("foo") / pl.col("pos_sum"))
).drop(["pos_sum", "neg_sum"])

print(result)

方式二:使用group_by+join实现

如果偏好先分组计算统计量再合并的模式,可以用group_by生成分组统计结果,再通过join关联回原表:

import polars as pl

df = pl.DataFrame(
    {
        "foo": [1, 3, -2, -1, 1, 2],
        "bar": [1, 1, 1, 1, 2, 2],
    }
)

# 分组计算正负总和
group_stats = df.group_by("bar").agg(
    pos_sum=pl.col("foo").filter(pl.col("foo") > 0).sum(),
    neg_sum=pl.col("foo").filter(pl.col("foo") < 0).sum()
)

# 关联原表并计算缩放值
result = df.join(group_stats, on="bar").with_columns(
    foo2=pl.when(pl.col("foo") < 0)
          .then(pl.col("foo") / pl.col("neg_sum"))
          .otherwise(pl.col("foo") / pl.col("pos_sum"))
).drop(["pos_sum", "neg_sum"])

print(result)

优化说明

  • 性能提升:两种优化方式都只执行一次分组内的正负总和计算,避免了原代码中when/then分支里重复调用filter+sum的冗余计算,大数据量下优势明显。
  • 可读性增强:将统计逻辑和缩放逻辑分离,代码结构更清晰,后续维护更方便。
  • 鲁棒性扩展:如果分组内只有正值或只有负值,filter会返回空序列,sum()会得到0,此时除法会报错。可以根据需求添加判断,比如:
    foo2=pl.when(pl.col("foo") < 0)
          .then(pl.col("foo") / pl.when(pl.col("neg_sum") != 0).then(pl.col("neg_sum")).otherwise(1))
          .otherwise(pl.col("foo") / pl.when(pl.col("pos_sum") != 0).then(pl.col("pos_sum")).otherwise(1))
    

输出结果与你的原代码完全一致:

shape: (6, 3)
┌─────┬─────┬──────────┐
│ foo ┆ bar ┆ foo2     │
│ --- ┆ --- ┆ ---      │
│ i64 ┆ i64 ┆ f64      │
╞═════╪═════╪══════════╡
│ 1   ┆ 1   ┆ 0.25     │
│ 3   ┆ 1   ┆ 0.75     │
│ -2  ┆ 1   ┆ 0.666667 │
│ -1  ┆ 1   ┆ 0.333333 │
│ 1   ┆ 2   ┆ 0.333333 │
│ 2   ┆ 2   ┆ 0.666667 │
└─────┴─────┴──────────┘

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:05:18