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

Polars中如何实现DataFrame行一对一映射?Join如何强制1:1映射?

实现Polars DataFrame的1:1重复行映射

Polars 原生 join 方法没有提供类似 Pandas 的 validate 参数来强制1:1映射,但可以通过分组内添加匹配序号+基于序号的连接实现需求,避免重复键产生的笛卡尔积,得到组内一对一的配对结果。

具体实现步骤与代码

1. 拆分源数据并添加分组内序号

先对两个源数据集,按指定的连接键分组,给每组内的重复行添加自增的唯一序号,确保同一分组内的行有可用于1:1匹配的标识:

import polars as pl

# 原始输入数据
df = pl.from_repr("""
┌──────┬──────────────────┬──────┬───────┬───────┬──────────┬────────┬──────────────────────────┐
│ id   ┆ partition_number ┆ type ┆ state ┆ price ┆ quantity ┆ source ┆ some_other_random_column │
│ ---  ┆ ---              ┆ ---  ┆ ---   ┆ ---   ┆ ---      ┆ ---    ┆ ---                      │
│ str  ┆ str              ┆ str  ┆ i64   ┆ f64   ┆ i64      ┆ i64    ┆ i64                      │
╞══════╪══════════════════╪══════╪═══════╪═══════╪══════════╪════════╪══════════════════════════╡
│ s1_1 ┆ p1               ┆ A    ┆ 1     ┆ 100.0 ┆ 10       ┆ 1      ┆ 1001                     │
│ s1_2 ┆ p1               ┆ A    ┆ 1     ┆ 100.0 ┆ 10       ┆ 1      ┆ 1001                     │
│ s1_3 ┆ p2               ┆ B    ┆ 2     ┆ 150.0 ┆ 20       ┆ 1      ┆ 1002                     │
│ s1_4 ┆ p3               ┆ C    ┆ 1     ┆ 200.0 ┆ 30       ┆ 1      ┆ 1003                     │
│ s2_1 ┆ p1               ┆ A    ┆ 1     ┆ 100.0 ┆ 10       ┆ 2      ┆ 1004                     │
│ s2_2 ┆ p1               ┆ A    ┆ 1     ┆ 100.0 ┆ 10       ┆ 2      ┆ 1004                     │
│ s2_3 ┆ p1               ┆ A    ┆ 1     ┆ 100.0 ┆ 10       ┆ 2      ┆ 1004                     │
│ s2_4 ┆ p2               ┆ B    ┆ 2     ┆ 150.0 ┆ 20       ┆ 2      ┆ 1005                     │
│ s2_5 ┆ p4               ┆ D    ┆ 1     ┆ 250.0 ┆ 40       ┆ 2      ┆ 1006                     │
└──────┴──────────────────┴──────┴───────┴───────┴──────────┴────────┴──────────────────────────┘
""")

# 拆分源数据
source1 = df.filter(pl.col('source') == 1)
source2 = df.filter(pl.col('source') == 2)

# 定义连接键
join_keys = ['partition_number', 'type', 'state', 'price', 'quantity']

# 给每个分组添加自增匹配序号
source1_with_idx = source1.with_columns(
    pl.int_range(0, pl.count()).over(join_keys).alias('match_idx')
)
source2_with_idx = source2.with_columns(
    pl.int_range(0, pl.count()).over(join_keys).alias('match_idx')
)

2. 执行1:1连接

使用原连接键+新增的match_idx作为连接条件,实现组内一对一匹配:

# 执行内连接,确保1:1配对
overlap_1to1 = source1_with_idx.join(
    source2_with_idx,
    on=join_keys + ['match_idx'],
    how='inner',
    suffix='_other'
)

# 生成完整格式的输出
result_full = overlap_1to1.drop('match_idx')
print(result_full)

输出结果与期望一致:

shape: (3, 9)
┌──────┬──────────────────┬──────┬───────┬───────┬──────────┬────────┬──────────────────┬──────────┐
│ id   ┆ partition_number ┆ type ┆ state ┆ price ┆ quantity ┆ source ┆ some_other_rando ┆ id_other │
│ ---  ┆ ---              ┆ ---  ┆ ---   ┆ ---   ┆ ---      ┆ ---    ┆ m_column         ┆ ---      │
│ str  ┆ str              ┆ str  ┆ i64   ┆ f64   ┆ i64      ┆ i64    ┆ ---              ┆ str      │
│      ┆                  ┆      ┆       ┆       ┆          ┆        ┆ i64              ┆          │
╞══════╪══════════════════╪══════╪═══════╪═══════╪══════════╪════════╪══════════════════╪══════════╡
│ s1_1 ┆ p1               ┆ A    ┆ 1     ┆ 100.0 ┆ 10       ┆ 1      ┆ 1001             ┆ s2_1     │
│ s1_2 ┆ p1               ┆ A    ┆ 1     ┆ 100.0 ┆ 10       ┆ 1      ┆ 1001             ┆ s2_2     │
│ s1_3 ┆ p2               ┆ B    ┆ 2     ┆ 150.0 ┆ 20       ┆ 1      ┆ 1002             ┆ s2_4     │
└──────┴──────────────────┴──────┴───────┴───────┴──────────┴────────┴──────────────────┴──────────┘

3. 生成简化输出

如果只需要id与id_other的映射关系,直接选择对应列即可:

result_simple = overlap_1to1.select(['id', 'id_other'])
print(result_simple)

输出:

shape: (3, 2)
┌──────┬──────────┐
│ id   ┆ id_other │
│ ---  ┆ ---      │
│ str  ┆ str      │
╞══════╪══════════╡
│ s1_1 ┆ s2_1     │
│ s1_2 ┆ s2_2     │
│ s1_3 ┆ s2_4     │
└──────┴──────────┘

关键说明

  • pl.int_range(0, pl.count()).over(join_keys):在每个分组内生成从0开始的连续整数,确保同一分组内的重复行有唯一匹配标识,彻底避免笛卡尔积。
  • 使用inner连接时,只会保留两边都有对应序号的行,最终结果行数不会超过左表(source1)的行数,符合“最多取左表行数”的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 01:09:49