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

如何在Polars DataFrame中按ID分组应用Scaler进行归一化

按ID分组实现MinMax归一化的正确方法

你的两种错误方法核心问题在于没搞清楚Polars表达式和sklearn工具的适配逻辑:

  • 第一种方法里,scaler.fit_transform()返回的是numpy数组,不是Polars表达式,所以没法调用.over()方法。
  • 第二种方法里,agg()只接受Polars表达式,不能直接把sklearn的函数套在pl.col()上,因为scaler不认识Polars的Expr对象。

下面提供两种可行的实现方式:

方法一:用Polars原生表达式手动实现(推荐,无需依赖sklearn)

MinMax归一化的公式是 (x - min(x)) / (max(x) - min(x)),直接用Polars的窗口函数over()就能按ID分组计算:

import polars as pl

df = pl.DataFrame(
    {
        "ID": [1,1,2,2,3,3],
        "Values": [1,2,3,4,5,6]
    }
)

df = df.with_columns(
    Value_scaled=(pl.col("Values") - pl.col("Values").min().over("ID")) 
                 / (pl.col("Values").max().over("ID") - pl.col("Values").min().over("ID"))
)

print(df)

输出结果:

shape: (6, 3)
┌─────┬────────┬──────────────┐
│ ID  ┆ Values ┆ Value_scaled │
│ --- ┆ ---    ┆ ---          │
│ i64 ┆ i64    ┆ f64          │
╞═════╪════════╪══════════════╡
│ 1   ┆ 1      ┆ 0.0          │
│ 1   ┆ 2      ┆ 1.0          │
│ 2   ┆ 3      ┆ 0.0          │
│ 2   ┆ 4      ┆ 1.0          │
│ 3   ┆ 5      ┆ 0.0          │
│ 3   ┆ 6      ┆ 1.0          │
└─────┴────────┴──────────────┘

如果有多列需要归一化,可以用循环批量处理:

cols_to_scale = ["Values", "Other_col"]  # 假设还有Other_col需要处理
for col in cols_to_scale:
    df = df.with_columns(
        (pl.col(col) - pl.col(col).min().over("ID")) 
        / (pl.col(col).max().over("ID") - pl.col(col).min().over("ID"))
        .alias(f"{col}_scaled")
    )

方法二:结合group_by.apply调用sklearn的MinMaxScaler

如果你一定要用sklearn的工具,可以用group_by().apply()对每个分组单独处理:

import polars as pl
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()

df = pl.DataFrame(
    {
        "ID": [1,1,2,2,3,3],
        "Values": [1,2,3,4,5,6]
    }
)

def scale_group(group):
    # sklearn要求输入是2D数组,转换后将结果展平为1D Series
    scaled_values = scaler.fit_transform(group.select("Values").to_numpy()).flatten()
    return group.with_columns(pl.Series("Value_scaled", scaled_values))

df_scaled = df.group_by("ID").apply(scale_group)
print(df_scaled)

这个方法的逻辑是:每个ID分组的子DataFrame会被传入scale_group函数,在函数内用scaler处理指定列,再把结果作为新列返回,最后Polars会自动合并所有分组结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 23:22:13