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

如何用另一DataFrame的多行替换pandas DataFrame中的对应行?

解决Pandas多DataFrame合并保留行与列的问题

问题描述

定义的两个Pandas DataFrame如下:

import pandas as pd

left = pd.DataFrame({"A": [1, 2], "B": ["a", "b"]})
left["C"] = pd.Series(dtype="int64")

right = pd.DataFrame({"A": [1, 1], "B": ["a", "a"], "C": [10, 20]})

背景说明:right由left经loc过滤并添加列得到,匹配列的值一致,right可能有额外列。需要将多个right依次合并到left,期望输出为:

A   B   C
0  1   a  10
1  1   a  20
2  2   b  NaN

尝试的三种方法均存在问题:

  • loc赋值:left.loc[left["A"] == right["A"]] = right,得到正确列但丢失一行;
  • merge:left.merge(right, on="A", how="left"),得到所有行但列名被重命名,后续合并会更麻烦;
  • join:left.join(right, on="A", how="left", rsuffix="R"),既丢失行又重命名列。

解决方案

要实现需求,核心是保留right的所有匹配行,同时保留left中未匹配的行,推荐两种实用方法:

方法1:拼接匹配行与未匹配行(简单直接)

# 提取left中未出现在right里的行(按A列判断)
unmatched_rows = left[~left["A"].isin(right["A"])]
# 拼接right的所有行和未匹配行,重置索引
final_df = pd.concat([right, unmatched_rows], ignore_index=True)
# 可选:按A列排序让结果更规整
final_df = final_df.sort_values(by="A", ignore_index=True)

运行后得到的结果完全符合预期:

A  B     C
0  1  a  10.0
1  1  a  20.0
2  2  b   NaN

方法2:Merge+字段覆盖(适合多right依次合并场景)

如果后续要合并多个类似的right,这种方法不会出现列名混乱的问题:

# 以A、B为匹配键,outer merge保留所有行
merged = left.merge(right, on=["A", "B"], how="outer", suffixes=("", "_tmp"))
# 用right的C值覆盖原C列的空值,删除临时列
merged["C"] = merged["C_tmp"].combine_first(merged["C"])
merged = merged.drop(columns=["C_tmp"]).reset_index(drop=True)

后续合并新的right时,只需将merged作为新的left,重复上述merge和字段覆盖步骤即可,始终保持列名一致。

之前方法的问题原因

  • loc赋值:left["A"] == right["A"]会做广播匹配,只能匹配到left中第一行A=1的记录,无法容纳right的两行数据,导致丢行;
  • 仅按A列merge:会让left的A=1行和right的两行生成笛卡尔积,同时产生C_x、C_y这类重复列;
  • join:默认按索引匹配,指定on="A"后同样会出现笛卡尔积和列名重复,且索引不对齐会导致丢行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 06:45:05