

新闻资讯
技术学院本文介绍一种高效、可扩展的方法,使用 pd.concat() 配合布尔索引实现两表按指定列(支持单列或多列)合并:保留 df2 的全部行,仅补充 df1 中在 df2 中完全不存在的行(含重复),避免 combine_first 导致的重复膨胀问题。
在 Pandas 数据处理中,当需要“以 df2 为主、df1 为辅”合并两个结构相同的数据框(即:保留 df2 的所有行,同时只追加 df1 中在 df2 中完全未出现过的记录(包括重复行)),直接使用 combine_first 或 merge 往往会因索引对齐逻辑导致重复行被错误广播——正如示例中 A=123 的行从 df2 的 4 行 + df1 的 2 行,意外膨胀为 8 行。
正确解法是:显式分离“覆盖部分”与“补充部分”,再垂直拼接:
import pandas as pd from io import StringIO # 示例数据 csv1_data = """A,B,C,D 123,xyz,S1,1111 123,xyz,S1,1111 234,mno,S3,2222 999,abc,S9,9999 999,abc,S9,9999""" csv2_data = """A,B,C,D 123,abc,S1,1234 123,abc,S1,1234 123,abc,S1,1234 123,cde,S2,2345 234,nop,S3, 567,pqr,S5,5555""" df1 = pd.read_csv(StringIO(csv1_data), dtype=str, keep_default_na=False) df2 = pd.read_csv(StringIO(csv2_data), dtype=str, keep_default_na=False) # ✅ 核心逻辑:取 df2 全部 + df1 中 A 值不在 df2.A 中的行(保留原始重复) key_col = 'A' result = pd.concat([ df2, df1[~df1[key_col].isin(df2[key_col])] ], ignore_index=True) print(result)
输出:
A B C D 0 123 abc S1 1234 1 123 abc S1 1234 2 123 abc S1 1234 3 123 cde S2 2345 4 234 nop S3 5 567 pqr S5 5555 6 999 abc S9 9999 7 999 abc S9 9999
当关键标识不止一列(如 ['A', 'B'] 或 ['A', 'A1', 'A2']),只需将列名列表传入,并利用 MultiIndex.isin() 进行精确匹配:
key_cols = ['A'] # 可动态替换为 ['A', 'B']、['A', 'A1', 'A2'] 等 # 构建 MultiIndex 进行成员判断 df1_mask = ~df1.set_index(key_cols).index.isin(df2.set_index(key_cols).index) result = pd.concat([df2, df1[df1_mask]], ignore_index=True)
? 性能提示:该方法时间复杂度为 O(n + m),远优于基于索引重排的 combine_first(易触发内部广播),特别适合百万级数据场景。
综上,pd.concat([df2, df1[~df1[key].isin(df2[key])]]) 是解决“主从式去重合并”的简洁、健壮且高性能的标准范式,兼顾可读性与工程可维护性。