You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Polars中如何使用布尔列表列作为掩码过滤另一列表列

Polars 用布尔列表列过滤另一列列表元素的实现方法

不需要走explode、过滤、聚合、join的繁琐流程,Polars 原生就支持这类跨列表的按位掩码过滤操作,根据你使用的版本可以选对应写法:

最简写法(Polars 0.20.0 及以上版本)

高版本Polars的list.filter原生支持直接传入同长度的布尔列表作为掩码,一行代码就能搞定:

import polars as pl

df = pl.DataFrame({
    'a': [[True, False], [False, True]],
    'b': [['name1', 'name2'], ['name3', 'name4']]
})

result = df.with_columns(
    filtered_b = pl.col("b").list.filter(pl.col("a"))
)

运行后得到的结果如下,完全符合过滤预期:

shape: (2, 3)
┌───────────────┬────────────────────┬─────────────┐
│ a             ┆ b                  ┆ filtered_b  │
│ ---           ┆ ---                ┆ ---         │
│ list[bool]    ┆ list[str]          ┆ list[str]   │
╞═══════════════╪════════════════════╪═════════════╡
│ [true, false] ┆ ["name1", "name2"] ┆ ["name1"]   │
│ [false, true] ┆ ["name3", "name4"] ┆ ["name4"]   │
└───────────────┴────────────────────┴─────────────┘

这个写法会自动校验同一行里两个列表的长度是否匹配,长度不一致时会直接抛出错误,刚好适配你提到的「每行a、b列表长度始终一致」的前提,不会出现数据错位的问题。

兼容旧版本的写法

如果用的是低于0.20的Polars版本,可以用zip_strict先把两列列表按位置打包成结构体列表,再做内部过滤:

result = df.with_columns(
    filtered_b = pl.zip_strict("a", "b").list.eval(
        pl.element().filter(pl.element().struct.field("a"))
    ).list.struct.field("b")
)

这个写法的逻辑和高版本的内置实现逻辑一致,同样带严格等长校验、全程向量化执行,没有额外性能损耗。

关于.list.eval无法跨列运算的说明

.list.eval默认的执行上下文是单个列表的内部元素上下文,默认无法直接引用同一行其他列的值,必须先把需要用到的多列值打包到同一个列表结构里,才能在eval逻辑里访问到对应字段。

和explode+join的方案比,上面两种原生实现不需要构造关联键、不需要分组聚合、没有join开销,全程是向量化运算,数据量越大性能优势越明显,代码也更简洁易维护。

内容的提问来源于stack exchange,提问作者cccs31

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:42:25