merge() 默认 inner 连接,仅保留两表共有的键,导致结果行数减少;业务中多需 left 连接(how="left")以确保左表记录完整,如订单主表补维度。

merge() 默认是 inner 连接,但多数业务场景需要 left
很多人一上来就写 pd.merge(df1, df2, on="id"),发现结果行数变少了,还以为数据丢了。其实这是 merge() 默认 how="inner" 导致的——只保留两表都有的 id。报表、宽表构建、主表补维度这类任务,通常得用 how="left",确保左表(比如订单主表)所有记录都在。
常见错误现象:len(result) ,尤其当右表(如用户画像表)缺失部分 <code>id 时,inner 会直接过滤掉这些订单。
-
how="left":保左表全量,右表匹配不上的字段填NaN -
how="outer":并集,适合做数据覆盖检查,但结果可能膨胀严重 -
how="right"很少用,逻辑上等价于调换左右表 +how="left" - 别依赖默认值,显式写
how=参数,避免协作时歧义
on、left_on、right_on 的选法决定关联是否成立
关联失败往往不是语法错,而是键没对齐。比如左表用 "user_id",右表用 "uid",必须用 left_on="user_id" 和 right_on="uid" 显式指定,不能只靠 on。
使用场景举例:左表是交易日志(含 "order_no"),右表是物流单(含 "order_number"),这时必须分开指定字段名。
- 两表字段名一致 → 用
on="col_name" - 字段名不同 → 必须用
left_on和right_on成对出现 - 多字段联合关联(如
("date", "region"))→on或left_on/right_on都传列表,顺序要一致 - 字段类型不一致(比如一表是
str,一表是int)会导致静默匹配失败,merge 后全为NaN,务必提前用df.dtypes检查
suffixes 参数不设好,列名冲突会让后续代码崩
两表都有 "name" 或 "status" 这类通用字段时,merge 默认加 "_x" 和 "_y" 后缀。但如果你后续写 result["name_x"],别人读代码根本猜不出哪个是主表的 name。
更糟的是,如果没注意后缀,直接写 result["name"],会报 KeyError —— 因为原始列名已不存在。
- 用
suffixes=("_l", "_r")比默认更直观,一眼看出来源 - 如果右表字段确定不会参与计算(比如只用来取
"city"),可用columns提前筛选右表列,减少冗余 - merge 后立刻检查
result.columns,确认关键字段是否按预期命名
大数据量下 merge 性能差?先看索引和重复键
merge 变慢,90% 不是因为 pandas 本身,而是键上有大量重复或没索引。比如左表 100 万订单,右表 10 万用户,但用户表里 "city" 作为关联键有 5000 个重复值,merge 就会爆炸式生成中间组合。
性能影响比想象中大:无索引时,pandas 对每行做 O(n) 查找;有索引且键唯一,可降到接近 O(1)。
- 用
df.set_index("key_col", drop=False)预设索引(仅当该列唯一且稳定时) - 检查重复:
df.key_col.duplicated().sum(),高重复率键慎用作关联依据 - 内存不够?优先删掉右表无关列(
df[["key", "needed_col"]]),比调参数更有效 - 真超千万行?考虑
dask.dataframe.merge或导出到 DuckDB 再 join
关联逻辑看似简单,但键的语义一致性、字段类型、重复分布、列名管理,每个环节松动一点,结果就偏一点。实际跑通 merge 后,花 30 秒看一眼 result.shape 和 result.isna().sum(),比重跑三遍强。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











