Polars中join_asof能否禁止精确匹配?无该功能时的替代方案
Polars中如何实现类似pandas merge_asof的allow_exact_matches=False功能?
问题背景
在pandas中,我们可以给merge_asof传入allow_exact_matches=False参数,禁止精确匹配行为。示例代码如下:
import pandas as pd df1 = pd.DataFrame({ "a": [1, 2, 3, 4, 5, 6, 7] }) df2 = pd.DataFrame({ "a": [1, 3, 5, 7], "b": [1, 3, 5, 7] }) # forward方向,禁止精确匹配 pd.merge_asof(df1, df2, on="a", direction='forward', allow_exact_matches=False) # 输出的b列:[3, 3, 5, 5, 7, 7, None] # backward方向,禁止精确匹配 pd.merge_asof(df1, df2, on="a", direction='backward', allow_exact_matches=False) # 输出的b列:[None, 1, 1, 3, 3, 5, 5]
但Polars的join_asof并没有提供直接对应的参数,因此需要通过替代方案实现相同效果。
替代解决方案
目前Polars没有直接实现allow_exact_matches=False的参数,但可以通过先执行常规asof join,再清空精确匹配结果的方式模拟该功能:
模拟forward方向禁止精确匹配
import polars as pl df1 = pl.DataFrame({"a": [1, 2, 3, 4, 5, 6, 7]}) df2 = pl.DataFrame({"a": [1, 3, 5, 7], "b": [1, 3, 5, 7]}) # 第一步:执行常规forward方向asof join result_forward = df1.join_asof(df2, on="a", direction="forward") # 第二步:将精确匹配的行的结果列置空 result_forward = result_forward.with_columns( pl.when(pl.col("a") == pl.col("b")).then(None).otherwise(pl.col("b")).alias("b") ) print(result_forward) # 输出结果的b列:[3, 3, 5, 5, 7, 7, None]
模拟backward方向禁止精确匹配
# 第一步:执行常规backward方向asof join result_backward = df1.join_asof(df2, on="a", direction="backward") # 第二步:将精确匹配的行的结果列置空 result_backward = result_backward.with_columns( pl.when(pl.col("a") == pl.col("b")).then(None).otherwise(pl.col("b")).alias("b") ) print(result_backward) # 输出结果的b列:[None, 1, 1, 3, 3, 5, 5]
通用适配写法
如果匹配键列与结果列名称不同,或者担心列名冲突,可以通过标记精确匹配行的方式实现,更具通用性:
# 执行asof join,Polars会自动给右表的重复列添加后缀(如a_right) result = df1.join_asof(df2, on="a", direction="forward") # 标记精确匹配的行 result = result.with_columns( is_exact_match=(pl.col("a") == pl.col("a_right")).alias("is_exact_match") ) # 清空精确匹配行的结果列 result = result.with_columns( pl.when(pl.col("is_exact_match")).then(None).otherwise(pl.col("b")).alias("b") ) # 清理临时列 result = result.drop("is_exact_match", "a_right")
内容的提问来源于stack exchange,提问作者T.H Rice
相关产品推荐
相关产品推荐

