如何在 Polars 中将标量数值广播加到 List 列的每个元素上

polars 1.10.0+ 支持 list 列与标量列的直接算术广播(如 `pl.col("lst") + pl.col("val")`) ,无需 `map_elements` 或嵌套 `list.eval`,简洁高效地实现逐元素加法。

在 Polars 中,对 List 列(如 pl.List 类型)执行“按行广播运算”——即把同一行中另一列的标量值加到该行 List 的每个元素上——曾长期受限于 list.eval 不支持跨列引用的限制。但自 Polars v1.10.0 起,这一场景已原生支持:List 列可直接与同长度的标量列进行算术运算,自动完成元素级广播

✅ 推荐方案(Polars ≥ 1.10.0):

import polars as pl

df = pl.DataFrame({
    'lst': [[0, 1], [9, 8]],
    'val': [3, 4]
})

result = df.with_columns(
    pl.col("lst") + pl.col("val")
)
print(result)

输出:

shape: (2, 2)
┌───────────┬─────┐
│ lst       ┆ val │
│ ---       ┆ --- │
│ list[i64] ┆ i64 │
╞═══════════╪═════╡
│ [3, 4]    ┆ 3   │
│ [13, 12]  ┆ 4   │
└───────────┴─────┘

⚠️ 注意事项:

  • 此语法要求 Polars 版本 ≥ 1.10.0(请通过 pip install --upgrade polars 更新);
  • 运算自动按行对齐:第 i 行 lst 中的每个元素 + 第 i 行 val 的值;
  • 支持所有基础算术操作(+

    , -, *, /, //, %),语义与 NumPy/Pandas 广播一致;
  • 若 lst 中列表长度不一,仍能正确处理(无需预填充)。

? 替代方案(兼容旧版本或特殊需求):
若需兼容

# 适用于等长列表(默认 n_field_strategy="first")
df.with_columns(
    pl.col("lst").list.to_struct() + pl.struct("val")
)

# 若列表长度不一,推荐显式指定策略以避免截断
df.with_columns(
    (pl.col("lst").list.to_struct(n_field_strategy="max_width") 
     + pl.struct("val"))
)

⚠️ 注意:此方式返回 struct 类型而非 list,后续需用 .struct.unnest() 或字段索引访问,灵活性略低。

? 总结:
优先使用 pl.col("lst") + pl.col("val") —— 它是官方推荐、性能最优、语义最清晰的解决方案。避免过时的 list.eval(pl.element() + ...) 模式(会报错)或低效的 map_elements(丢失查询优化与类型推断)。升级 Polars 至最新稳定版,即可解锁这一关键生产力改进。