Примените Scaler() к каждому идентификатору в фрейме данных Polars

У меня есть набор данных с несколькими столбцами и столбцом идентификатора. Каждый идентификатор может иметь разные величины и размеры в этих столбцах. Я хочу нормализовать столбцы для каждого идентификатора отдельно.

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]}
)

Если я это сделаю, я буду использовать масштабатор всего кадра данных, и я хотел бы использовать scaler() для каждого идентификатора.

Я попробовал это:

(
    df
    .with_columns(
        Value_scaled = scaler.fit_transform(df.select(pl.col("Value"))).over("ID"),
    )
)

Но: AttributeError: 'numpy.ndarray' object has no attribute 'over'

И я также попробовал использовать group_by()

(
    df
    .group_by(
        pl.col("ID")
    ).agg(
        scaler.fit_transform(pl.col("Value")).alias("Value_scaled")
    )
)

И я получаю:

TypeError: float() argument must be a string or a real number, not 'Expr'

🤔 А знаете ли вы, что...
Python подходит для начинающих программистов благодаря своей простоте и читаемости кода.


1
50
1

Ответ:

Решено

Следуя определению, изложенному в документации, функциональность MinMaxScaler можно легко реализовать с помощью собственного API-интерфейса выражений Polars.

def min_max_scaler(x: str | pl.Expr) -> pl.Expr:
    if isinstance(x, str):
        x = pl.col(x)
    return (x - x.min()) / (x.max() - x.min())

Затем он совместим с оконными функциями Polars, такими как pl.Expr.over, чтобы применять масштабирование отдельно для каждого ID.

df.with_columns(min_max_scaler("Values").over("ID"))
shape: (6, 2)
┌─────┬────────┐
│ ID  ┆ Values │
│ --- ┆ ---    │
│ i64 ┆ f64    │
╞═════╪════════╡
│ 1   ┆ 0.0    │
│ 1   ┆ 1.0    │
│ 2   ┆ 0.0    │
│ 2   ┆ 1.0    │
│ 3   ┆ 0.0    │
│ 3   ┆ 1.0    │
└─────┴────────┘