
本文介绍如何在 Polars 中利用 pl.when() 和 pl.coalesce() 组合表达式字典,根据某列(如类别列)的值动态选择并执行对应表达式,高效生成新列,避免低效的 .apply() 或 Python 循环。
本文介绍如何在 polars 中利用 `pl.when()` 和 `pl.coalesce()` 组合表达式字典,根据某列(如类别列)的值动态选择并执行对应表达式,高效生成新列,避免低效的 `.apply()` 或 python 循环。
在 Polars 中,若需根据某一字符串列(如 "col1")的值,为每行选择不同的计算逻辑(例如 "a" 时计算 x * y,"b" 时仅取 x),不应使用 .apply() + Python lambda —— 这会强制退出 Polars 的惰性执行引擎,导致严重性能下降且无法利用并行优化。
正确做法是将表达式字典(expr_dict)转化为一组向量化条件表达式,并通过 pl.coalesce() 按优先级顺序“合并”结果。其核心逻辑是:对字典中每个键值对 (k, v),构造 pl.when(pl.col("col1") == k).then(v);pl.coalesce() 会从左到右返回第一个非空(non-null)结果,天然适配多分支场景。
以下是完整可运行示例:
import polars as pl
# 构建原始数据
df = pl.DataFrame({
"col1": ["a", "b", "a"],
"x": [1, 2, 3],
"y": [2, 2, 5]
})
# 定义表达式字典:键为 col1 可能的值,值为 Polars 表达式
expr_dict = {
"a": pl.col("x") * pl.col("y"),
"b": pl.col("x")
}
# 使用 when + coalesce 实现行级动态计算
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 │ └──────┴─────┴─────┴─────┘
✅ 关键优势:
- 全程保持 Polars 原生表达式链,支持惰性执行、查询优化与多线程加速;
-
pl.coalesce()自动处理未匹配键(返回null),如需兜底逻辑,可在末尾追加.otherwise(...)(注意:coalesce本身不支持otherwise,此时应改用嵌套when().then().otherwise()链,或在coalesce外层包裹fill_null()); - 支持任意复杂表达式(含聚合、窗口函数等),只要其输出与输入行数对齐。
⚠️ 注意事项:
- 字典键必须与
col1列的实际值类型一致(如均为str); - 若存在字典未覆盖的
col1值(如"c"),对应r值为null,建议显式处理:r=pl.coalesce(...).fill_null(0); - 表达式顺序影响
coalesce优先级——若键有重叠逻辑(如通配符),请按预期匹配优先级排序字典项(Python 3.7+ 保持插入顺序)。
此模式是 Polars 中实现“策略分发”(strategy dispatch)或“规则引擎”的推荐范式,兼具性能、可读性与可维护性。

















