
本文介绍如何使用 Polars 的链式表达式,在单次 with_columns 调用中,将两个等长列表列(如 Movie 和 Count)按位置配对,并自动过滤掉任一元素为 null 的项,最终生成 struct 类型的配对结果。
本文介绍如何使用 polars 的链式表达式,在单次 `with_columns` 调用中,将两个等长列表列(如 movie 和 count)按位置配对,并自动过滤掉任一元素为 `null` 的项,最终生成 struct 类型的配对结果。
在 Polars 中处理嵌套列表列时,常需对齐、筛选并结构化多列数据。上述需求本质是:对两个同长度 list 列执行逐元素配对(zip),仅保留双方均非 null 的索引位置,并将有效配对封装为 struct。关键在于避免 Python 级循环,完全利用 Polars 的惰性计算和向量化 list 操作。
核心思路分三步:
- 定位有效索引:对 Movie 列调用 .list.eval(pl.element().is_not_null().arg_true()),返回一个包含所有非 null 元素下标的 list(如 [1]);
- 统一索引取值:用该索引 list 同时对 Movie 和 Count 两列执行 .list.gather(),实现“同步切片”;
- 结构化输出:将提取后的两个 scalar list(各含 1 个元素)传入 pl.struct(),自动生成 struct 字段。
以下是完整可运行示例:
import polars as pl
df = pl.DataFrame({
"Movie": [[None, "IT", "Joker"]],
"Count": [[30, 27, 42]],
})
result = df.with_columns(
pl.struct(
pl.col("Movie", "Count")
.list.gather(
pl.col("Movie").list.eval(pl.element().is_not_null().arg_true())
)
.list.first() # 提取内部 list(因 gather 返回 list[list],first 取首项)
).alias("data")
)
print(result)
⚠️ 注意事项:
- list.gather() 返回的是 list[list[T]],因此需 .list.first() 提取内层 list,确保 pl.struct() 接收的是两个平行的 scalar list;
- 若原始 list 长度不一致,gather 会报错——请确保输入列长度严格对齐;
- 若需保留多个有效配对(如 Movie=[None,"A","B"], Count=[10,None,30] → {"B",30}),当前逻辑仍适用,arg_true() 自动捕获所有非 null 下标;
- 如需扩展为多字段 struct(如加入 ID、Year),只需在 pl.struct() 中追加对应列名即可。
该方案完全在 Polars 表达式上下文中完成,无需 .apply() 或 Python UDF,兼顾性能与简洁性,是处理嵌套列表配对任务的推荐范式。










