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

Polars:在when/then表达式中用列值动态引用其他列

解决Polars中动态根据列名引用生成新列的问题

问题场景

需要生成新列res,规则如下:

  • 当frequency列非空且非NaN时,直接取frequency的值
  • 否则根据frequency_ref列指定的列名,从对应列取值
  • 兜底值为0.0

示例数据:

import polars as pl

df = pl.DataFrame(
    {
        "frequency": [0.5, None, None, None],
        "frequency_ref": ["a", "z", "a", "a"],
        "a": [1, 2, 3, 4],
        "z": [5, 6, 7, 8],
    }
)

期望结果:

res = pl.DataFrame(
    {
        "frequency": [0.5, None, None, None],
        "frequency_ref": ["a", "z", "a", "a"],
        "a": [1, 2, 3, 4],
        "z": [5, 6, 7, 8],
        "res": [0.5, 6, 3, 4]
    }
)

错误原因

你尝试的pl.col(pl.col("frequency_ref"))写法不合法:pl.col()要求传入字符串(列名)或DataType类型,不能直接传入表达式(Expr对象),因此触发TypeError: invalid input for "col". Expected "str" or "DataType", got 'Expr'.

最优解决方案

方法一:利用结构体(Struct)动态取值(推荐,性能更优)

将需要动态引用的列打包成结构体,通过frequency_ref的值作为键提取对应字段:

# 定义所有可能被引用的列集合
target_cols = ["a", "z"]

df = df.with_columns(
    pl.when(pl.col("frequency").is_not_null() & pl.col("frequency").is_not_nan())
    .then(pl.col("frequency"))
    # 可选:先验证引用列是否在目标集合中,避免无效列名报错
    .when(pl.col("frequency_ref").is_in(target_cols))
    .then(pl.struct(target_cols).struct.field(pl.col("frequency_ref")))
    .otherwise(0.0)
    .alias("res")
)

优势:

  • 无需硬编码每个列的when/then分支
  • 列名变更时仅需修改target_cols集合,扩展性强
  • 基于Polars向量化操作,大数据集下性能更优

方法二:利用pl.row动态索引列

通过pl.row接收表达式返回的列名字符串,直接取对应列的值:

df = df.with_columns(
    pl.when(pl.col("frequency").is_not_null() & pl.col("frequency").is_not_nan())
    .then(pl.col("frequency"))
    .then(pl.row(pl.col("frequency_ref")))
    .otherwise(0.0)
    .alias("res")
)

优势:代码更简洁,无需提前定义目标列集合;但pl.row是按行处理操作,大数据集下性能略逊于结构体方法。

对比硬编码方案

硬编码逐个列的when/then分支扩展性极差,列名新增或修改时需同步修改代码;上述两种方法仅需维护目标列集合或自动适配,大幅降低维护成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 01:02:11