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

如何在Polars中全连接/合并两个DataFrame并使用右侧数据更新左侧对应值?

如何在Polars中全连接/合并两个DataFrame并使用右侧数据更新左侧对应值?

看起来你遇到的问题是因为误用了所有共同列作为连接键,导致即使是同一个track_name,只要其他列(比如yield)存在差异,就会被判定为不同行,最终full join后出现了重复的8CEB45v1条目。要实现「右侧数据覆盖左侧对应行」的需求,我们需要调整连接逻辑,只以唯一标识列(比如track_name)作为匹配依据,再合并列时优先保留右侧的值。

下面提供两种实用的解决方案:

方法一:Full Join + Coalesce合并列

这种方法先基于唯一主键做全连接,再通过coalesce函数让右侧列值优先覆盖左侧,逻辑清晰且可控:

import polars as pl

left_csv = b"""
track_name,type,yield,group
8CEB45v1,corn,0.146957,A
A188v2,corn,0.86308,A
B73v6,corn,0.326076,A
CI6621v1,sweetcorn,0.0357792,A
CML103v1,sweetcorn,0.510464,A
""".strip()

right_csv = b"""
track_name,type,yield,group
8CEB45v1,corn,0.999,A
B1234,pepper,1,B
B1235,pepper,2,B
""".strip()

left = pl.read_csv(left_csv)
right = pl.read_csv(right_csv)

# 仅使用track_name作为唯一连接键
join_key = "track_name"

full_df = left.join(
    right,
    on=join_key,
    how="full",
    suffix="_right"  # 给右侧重复列加后缀区分
).select(
    join_key,
    # 对每一列,优先取右侧的值,右侧无值则保留左侧
    pl.coalesce("type_right", "type").alias("type"),
    pl.coalesce("yield_right", "yield").alias("yield"),
    pl.coalesce("group_right", "group").alias("group")
)

print(full_df)

运行后就能得到你想要的结果:

shape: (7, 4)
┌────────────┬───────────┬───────────┬───────┐
│ track_name ┆ type      ┆ yield     ┆ group │
│ ---        ┆ ---       ┆ ---       ┆ ---   │
│ str        ┆ str       ┆ f64       ┆ str   │
╞════════════╪═══════════╪═══════════╪═══════╡
│ 8CEB45v1   ┆ corn      ┆ 0.999     ┆ A     │
│ A188v2     ┆ corn      ┆ 0.86308   ┆ A     │
│ B73v6      ┆ corn      ┆ 0.326076  ┆ A     │
│ CI6621v1   ┆ sweetcorn ┆ 0.0357792 ┆ A     │
│ CML103v1   ┆ sweetcorn ┆ 0.510464  ┆ A     │
│ B1234      ┆ pepper    ┆ 1.0       ┆ B     │
│ B1235      ┆ pepper    ┆ 2.0       ┆ B     │
└────────────┴───────────┴───────────┴───────┘

方法二:Concat + Unique(更简洁)

如果你的需求就是「右侧数据覆盖左侧同主键行」,可以直接拼接两个DataFrame后去重,保留最后出现的行(也就是右侧的行),代码更简洁:

full_df = pl.concat([left, right]).unique(subset="track_name", keep="last")
print(full_df)

这个方法的逻辑很直观:把左侧数据放在前面,右侧数据放在后面,然后按track_name去重,保留最后一次出现的条目,自然就实现了右侧对左侧的更新。运行结果和方法一完全一致。

为什么你的原代码没生效?

你之前用matching_columns = list(set(left.columns) & set(right.columns))把所有共同列都设为连接键,这意味着只有当track_name、type、yield、group四列的值完全相同时,才会合并行。而右侧的8CEB45v1的yield值和左侧不同,所以被判定为不同行,导致full join后出现了重复条目。核心问题就是要使用唯一标识列作为连接键,而非所有共同列。

备注:内容来源于stack exchange,提问作者Pm740

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 11:22:58