如何在Polars中无需map_rows实现列的字典序比较过滤?
按字典序过滤Polars DataFrame行(无需map_rows)
初始数据
首先定义初始DataFrame:
import polars as pl df = pl.DataFrame({'a': [1, 1, 2, 0], 'b': [1, 4, 1, 5]})
输出结果:
shape: (4, 2) ┌─────┬─────┐ │ a ┆ b │ │ --- ┆ --- │ │ i64 ┆ i64 │ ╞═════╪═════╡ │ 1 ┆ 1 │ │ 1 ┆ 4 │ │ 2 ┆ 1 │ │ 0 ┆ 5 │ └─────┴─────┘
需求说明
需要按字典序过滤出(a, b)大于(1, 2)的行,规则为:先比较a与1,若a更大则直接满足;若a等于1,再比较b与2,b更大才满足。示例:
(1, 1) < (1, 2)→ 不保留(1, 3) > (1, 2)→ 保留(2, 1) > (1, 2)→ 保留
现有实现(使用map_rows)
目前通过map_rows可以实现需求,但希望找到更高效的向量化方法:
df.filter(df.map_rows(lambda row: (row[0], row[1]) > (1, 2))['map'])
正确输出:
shape: (2, 2) ┌─────┬─────┐ │ a ┆ b │ │ --- ┆ --- │ │ i64 ┆ i64 │ ╞═════╪═════╡ │ 1 ┆ 4 │ │ 2 ┆ 1 │ └─────┴─────┘
错误的过滤方式
单独对列进行或操作会包含不符合要求的行(比如(0,5)),不符合需求:
df.filter((pl.col("a") > 1) | (pl.col("b") > 2))
错误输出:
shape: (3, 2) ┌─────┬─────┐ │ a ┆ b │ │ --- ┆ --- │ │ i64 ┆ i64 │ ╞═════╪═════╡ │ 1 ┆ 4 │ │ 2 ┆ 1 │ │ 0 ┆ 5 │ └─────┴─────┘
无需map_rows的解决方案
方法1:逻辑表达式组合
直接用逻辑条件组合实现字典序规则,完全向量化:
df.filter((pl.col("a") > 1) | ((pl.col("a") == 1) & (pl.col("b") > 2)))
执行后得到正确结果,和map_rows输出一致。
方法2:元组直接比较
Polars支持直接对列构造的元组进行比较,写法更简洁直观,且效率更高:
df.filter((pl.col("a"), pl.col("b")) > (1, 2))
这个写法和map_rows的逻辑完全一致,但避免了逐行遍历,性能更优,输出结果同样正确。
内容的提问来源于stack exchange,提问作者ignoring_gravity
相关产品推荐
相关产品推荐

