如何在Polars中基于另一列表的值过滤列表?
问题与解决方案
问题背景
给定如下Polars DataFrame:
import polars as pl df = pl.DataFrame({ 'values': [[0, 1], [9, 8]], 'qc_flags': [["", "X"], ["T", ""]] })
其结构为:
shape: (2, 2) ┌───────────┬───────────┐ │ values ┆ qc_flags │ │ --- ┆ --- │ │ list[i64] ┆ list[str] │ ╞═══════════╪═══════════╡ │ [0, 1] ┆ ["", "X"] │ │ [9, 8] ┆ ["T", ""] │ └───────────┴───────────┘
需求是仅保留qc_flags中对应元素为""的values元素,期望结果:
shape: (2, 2) ┌───────────┬───────────┐ │ values ┆ qc_flags │ │ --- ┆ --- │ │ list[i64] ┆ list[str] │ ╞═══════════╪═══════════╡ │ [0] ┆ ["", "X"] │ │ [8] ┆ ["T", ""] │ └───────────┴───────────┘
尝试的代码及错误:
filtered = df.with_columns( pl.col("values").list.eval( pl.element().filter( pl.col("qc_flags").list.eval( pl.element() == "" ) ) ) )
报错信息:
ComputeError: eval函数中不允许使用命名列;请考虑使用element
错误原因
list.eval的作用域局限于当前列表的元素,无法直接访问DataFrame中的其他命名列(比如qc_flags),因此直接在values的list.eval里引用qc_flags会触发错误。
正确实现方式
方法一:使用list.zip配对过滤(推荐)
通过list.zip将values和qc_flags的元素一一配对,过滤出符合条件的项后提取对应值:
filtered = df.with_columns( pl.col("values") .zip(pl.col("qc_flags")) .list.filter(lambda pair: pair[1] == "") .list.map(lambda pair: pair[0]) .alias("values") )
方法二:通过结构体关联列元素
将两列打包成结构体列表,再通过list.eval过滤提取有效值:
filtered = df.with_columns interior封 impossible`万金0ime Faith 大 filtered = df.with_columns( pl.struct(["values", "qc_flags"]) .list.eval( pl.when(pl.element().struct.field("qc_flags") == "") .then(pl.element().struct.field("values")) ) .list.drop_nulls() .alias("values") )
两种方法运行后都能得到期望的输出结构。
内容的提问来源于stack exchange,提问作者Brodie Vidrine
相关产品推荐
相关产品推荐

