
本文介绍如何在 Polars 中利用 pl.when() 和 pl.coalesce() 组合表达式字典,根据某列的字符串键(如 "a"、"b")动态选择对应表达式,逐行计算生成新列,避免低效的 apply 或 Python 循环。
本文介绍如何在 polars 中利用 `pl.when()` 和 `pl.coalesce()` 组合表达式字典,根据某列的字符串键(如 `"a"`、`"b"`)动态选择对应表达式,逐行计算生成新列,避免低效的 `apply` 或 python 循环。
在 Polars 中,若需根据某一分类列(如 col1)的值,为每行选择不同的计算逻辑(例如 "a" 时用 x * y,"b" 时仅取 x),不应使用 apply() + lambda——这会触发 Python 级别循环,丧失 Polars 的向量化优势,且无法静态推断类型与优化执行计划。
正确做法是将表达式字典(expr_dict)转化为一系列条件分支,并通过 pl.coalesce() 实现“首个非 null 条件结果即生效”的语义。其核心逻辑是:
- 对字典中每个
(key, expr),构造pl.when(pl.col("col1") == key).then(expr) - 所有
when/then分支按顺序组合,由pl.coalesce()统一合并:返回第一个非null的计算结果
✅ 示例代码如下:
import polars as pl
df = pl.DataFrame({
"col1": ["a", "b", "a"],
"x": [1, 2, 3],
"y": [2, 2, 5]
})
expr_dict = {
"a": pl.col("x") * pl.col("y"),
"b": pl.col("x")
}
result = df.with_columns(
r = pl.coalesce(
pl.when(pl.col("col1") == k).then(v)
for k, v in expr_dict.items()
)
)
print(result)输出:
shape: (3, 4) ┌──────┬─────┬─────┬─────┐ │ col1 ┆ x ┆ y ┆ r │ │ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ i64 ┆ i64 │ ╞══════╪═════╪═════╪═════╡ │ a ┆ 1 ┆ 2 ┆ 2 │ │ b ┆ 2 ┆ 2 ┆ 2 │ │ a ┆ 3 ┆ 5 ┆ 15 │ └──────┴─────┴─────┴─────┘
⚠️ 注意事项:
-
键必须全覆盖或含兜底逻辑:若
col1出现字典中未定义的值(如"c"),对应行r将为null。如需默认值,可在coalesce末尾追加.otherwise(pl.lit(0))(Polars 0.20.0+ 支持)或提前补全字典。 -
表达式类型需兼容:所有
then()分支返回值类型应一致(如均为i64),否则 Polars 可能报类型推断错误;必要时可用cast()显式转换。 - 性能优势显著:该写法全程运行于 Rust 引擎,零 Python 开销,支持查询优化器自动融合、并行化及流式处理。
总结:pl.when().then().coalesce() 是 Polars 中实现“字典驱动条件计算”的标准范式,兼具表达力、性能与可维护性,应作为替代 apply 的首选方案。

















