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

如何为DataFrame每行动态设置polars Expr.cut的breaks参数?

解决Polars中基于动态列生成breaks的分箱问题

问题分析

你需要为DataFrame每行的Value列,基于该行的BinMin和BinMax动态生成50个等间隔的breaks,再用Expr.cut分箱。但np.linspace无法直接接受Polars的表达式对象,导致报错。核心原因是cut的breaks参数默认需要静态序列,而你需要行级动态生成breaks。

解决方案

方法1:使用map_elements结合自定义函数

通过将每行的Value、BinMin、BinMax打包为结构体,再用map_elements调用自定义函数生成breaks并分箱,这是最直观的实现方式:

import numpy as np
import polars as pl

def dynamic_cut(row):
    # 为当前行生成50个等间隔的breaks
    breaks = np.linspace(row["BinMin"], row["BinMax"], 50)
    # 对当前行的Value进行分箱
    return pl.Series([row["Value"]]).cut(breaks)[0]

df = pl.DataFrame({"Value": [12, 35, 80], "BinMin": [0, 10, 50], "BinMax": [100, 60, 90]})

result = df.with_columns(
    pl.struct(["Value", "BinMin", "BinMax"])
    .map_elements(dynamic_cut, return_dtype=pl.Categorical)
    .alias("Bin")
)

print(result)

输出结果:

┌───────┬────────┬────────┬───────────────────────┐
│ Value ┆ BinMin ┆ BinMax ┆ Bin                   │
│ ---   ┆ ---    ┆ ---    ┆ ---                   │
│ i64   ┆ i64    ┆ i64    ┆ cat                   │
╞═══════╪════════╪════════╪═══════════════════════╡
│ 12    ┆ 0      ┆ 100    ┆ (10.204, 12.245]      │
│ 35    ┆ 10     ┆ 60     ┆ (34.694, 35.714]      │
│ 80    ┆ 50     ┆ 90     ┆ (79.592, 80.408]      │
└───────┴────────┴────────┴───────────────────────┘

方法2:纯Polars向量化实现(无numpy依赖)

如果想避免使用numpy,可利用Polars的sequence函数生成每行的breaks序列,再通过map_elements完成分箱:

import polars as pl

df = pl.DataFrame({"Value": [12, 35, 80], "BinMin": [0, 10, 50], "BinMax": [100, 60, 90]})

result = df.with_columns(
    # 生成每行的breaks序列:50个等间隔点
    breaks = pl.sequence(
        start=pl.col("BinMin"),
        end=pl.col("BinMax"),
        length=50,
        dtype=pl.Float64
    ),
    # 对每行的Value和breaks进行分箱
    Bin = pl.struct(["Value", "breaks"])
    .map_elements(lambda x: pl.Series([x["Value"]]).cut(x["breaks"])[0], return_dtype=pl.Categorical)
).drop("breaks")

print(result)

注意事项

  • map_elements是行级操作,若数据量极大,性能会略低于完全向量化操作,但对于大多数场景足够高效。
  • 若需要分箱后的数值标签而非区间字符串,可在cut中添加labels参数,或用pl.col("Bin").cast(pl.Utf8).str.extract(r"(\d+\.?\d*)", 1).cast(pl.Float64)提取区间下限/上限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:25:55