如何在Polars中基于date+多字段OR条件实现DataFrame连接?
在Polars中实现多字段OR逻辑的连接需求
完全可以实现。你需要先基于date字段对齐数据,再通过org_id、org_slug、org_name的OR条件匹配,同时处理空值避免无效匹配。以下是两种高效的实现方式:
方法一:使用Join的Condition参数(推荐)
Polars的join方法支持通过condition参数指定额外的匹配逻辑,结合on="date"先对齐日期,再在同日期范围内应用OR条件。同时加入is_not_null判断,避免空值之间的错误匹配。
示例代码
import polars as pl # 构造示例数据集 df1 = pl.DataFrame({ "date": ["2024-01-01", "2024-01-01", "2024-01-02"], "org_id": [1, None, 3], "org_slug": ["abc", "def", None], "org_name": ["Org A", "Org B", "Org C"], "value1": [10, 20, 30] }) df2 = pl.DataFrame({ "date": ["2024-01-01", "2024-01-01", "2024-01-02"], "org_id": [1, 2, None], "org_slug": ["abc", None, "org-c"], "org_name": ["Org A", "Org B", "Org C"], "value2": [100, 200, 300] }) # 执行连接 result = df1.join( df2, on="date", how="inner", # 根据需求选择连接类型:inner/left/right/full condition=( # org_id匹配(双方非空) (pl.col("org_id") == pl.col("org_id_right")) & pl.col("org_id").is_not_null() & pl.col("org_id_right").is_not_null() # 或org_slug匹配(双方非空) | (pl.col("org_slug") == pl.col("org_slug_right")) & pl.col("org_slug").is_not_null() & pl.col("org_slug_right").is_not_null() # 或org_name匹配(双方非空) | (pl.col("org_name") == pl.col("org_name_right")) & pl.col("org_name").is_not_null() & pl.col("org_name_right").is_not_null() ) ) print(result)
方法二:Cross Join + 过滤(适合小数据集)
如果数据集规模较小,可以先按date做笛卡尔积连接,再过滤符合OR条件的行。这种方式逻辑更直观,但数据量大时性能不如方法一。
示例代码
result = df1.join( df2, on="date", how="cross" ).filter( (pl.col("org_id") == pl.col("org_id_right")) & pl.col("org_id").is_not_null() & pl.col("org_id_right").is_not_null() | (pl.col("org_slug") == pl.col("org_slug_right")) & pl.col("org_slug").is_not_null() & pl.col("org_slug_right").is_not_null() | (pl.col("org_name") == pl.col("org_name_right")) & pl.col("org_name").is_not_null() & pl.col("org_name_right").is_not_null() ) print(result)
进阶:优先匹配逻辑
如果需要优先用org_id匹配,其次是org_slug,最后是org_name(避免同一日期下出现多个匹配结果),可以通过添加匹配优先级并去重实现:
result = df1.join( df2, on="date", how="left" ).with_columns( # 给匹配条件设置优先级:1=org_id,2=org_slug,3=org_name pl.when((pl.col("org_id") == pl.col("org_id_right")) & pl.col("org_id").is_not_null()).then(1) .when((pl.col("org_slug") == pl.col("org_slug_right")) & pl.col("org_slug").is_not_null()).then(2) .when((pl.col("org_name") == pl.col("org_name_right")) & pl.col("org_name").is_not_null()).then(3) .alias("match_priority") ).filter(pl.col("match_priority").is_not_null()) .sort("match_priority") .group_by(["date", "org_id", "org_slug", "org_name"]) .first() .drop("match_priority") print(result)
内容的提问来源于stack exchange,提问作者Tizianoreica
相关产品推荐
相关产品推荐

