Polars如何通过原生表达式计算DataFrame列表列的行级交集
Polars 原生实现两列列表的交集计算
最优方案(Polars 0.19.0+ 版本支持)
Polars 列表命名空间内置了原生集合交集方法,计算全程在Rust引擎侧执行,无Python跨语言调用开销,性能远高于apply实现,代码也最简洁:
import polars as pl df = pl.DataFrame({'a': [[1, 2, 3], [8, 9, 4]], 'b': [[2, 3, 4], [4, 5, 6]]}) result = df.with_columns( c = pl.col("a").list.intersection(pl.col("b")) )
执行后输出结果完全符合预期:
shape: (2, 3) ┌───────────┬───────────┬───────────┐ │ a ┆ b ┆ c │ │ list[i64] ┆ list[i64] ┆ list[i64] │ ╞═══════════╪═══════════╪═══════════╡ │ [1, 2, 3] ┆ [2, 3, 4] ┆ [2, 3] │ │ [8, 9, 4] ┆ [4, 5, 6] ┆ [4] │ └───────────┴───────────┴───────────┘
低版本兼容方案
如果使用的Polars版本低于0.19.0,没有内置list.intersection接口,可以通过行号标记、explode展开、过滤匹配、重新聚合的纯表达式逻辑实现,同样不需要依赖apply调用Python函数:
result = ( df .with_row_index("row_id") # 复制待计算列用于展开匹配,保留原始列表列 .with_columns( pl.col("a").alias("a_exp"), pl.col("b").alias("b_exp") ) # 同时展开两列的复制列 .explode("a_exp", "b_exp") # 过滤出同一行下两列值相等的元素,即为交集元素 .filter(pl.col("a_exp") == pl.col("b_exp")) # 按行号分组还原原始结构 .group_by("row_id", maintain_order=True) .agg( pl.col("a").first(), pl.col("b").first(), pl.col("a_exp").alias("c") ) .drop("row_id") )
内容的提问来源于stack exchange,提问作者Vikash Balasubramanian
相关产品推荐
相关产品推荐

