用 pd.merge() 做左连接最直接,需设 how="left" 保留左表全部行、右表匹配填充,未匹配处补 nan;必须显式指定 on 或 left_on/right_on,避免默认 inner 连接或 keyerror。

用 pd.merge() 做 Left Join 最直接
Python Pandas 里没有叫 “LEFT JOIN” 的方法,但 pd.merge() 的 how='left' 参数就是标准左连接行为:保留左表全部行,右表只匹配上才填充,没匹配上的列填 NaN。
常见错误是漏写 how 参数,默认是 'inner',结果变成内连接,数据量突然变少却找不到原因。
-
left和right参数必须传 DataFrame,顺序不能反——左表是你想保留全部记录的那个 - 如果两表有同名列(比如都叫
'id'),默认会自动按同名列合并;否则必须显式指定left_on和right_on - 合并后索引会被丢弃,如需保留左表原始索引,加
left_index=True或先重置索引再 merge
import pandas as pd
df_left = pd.DataFrame({'id': [1, 2, 3], 'name': ['A', 'B', 'C']})
df_right = pd.DataFrame({'id': [2, 3, 4], 'score': [88, 95, 72]})
result = pd.merge(df_left, df_right, on='id', how='left')
当列名不一致时,必须用 left_on 和 right_on
SQL 里可以写 ON a.user_id = b.id,Pandas 对应的就是 left_on='user_id' + right_on='id'。只写一个参数会报错:MergeError: Must specify right_on or right_index。
注意:这两个参数值必须是字符串或列表,不能传 Series 或表达式;也不支持模糊匹配或函数转换(比如想按小写对齐,得先改列再 merge)。
- 若要按多列联合匹配,传列表:
left_on=['region', 'year'],right_on=['area', 'yr'] - 列名含空格或特殊字符?没问题,只要字符串能准确对应列名即可,Pandas 不校验合法性
- 如果某列在左表存在、右表不存在,
left_on仍可指定,但right_on必须指向右表真实列名,否则报KeyError
处理重复键导致的笛卡尔积膨胀
Left Join 本身不拒绝重复键,但如果左表某 id 出现 3 次、右表对应 id 也出现 2 次,结果就会产生 3×2=6 行——这不是 bug,是 SQL 标准行为,但常被忽略,导致行数远超预期。
检查方式很简单:len(result) > len(df_left) 就说明有重复键参与了匹配。这时候得决定是去重、聚合,还是接受膨胀。
- 快速排查:用
df_left['id'].duplicated().sum()和df_right['id'].duplicated().sum()分别看两边重复数 - 想避免膨胀?可在 merge 前对右表去重:
df_right.drop_duplicates(subset='id'),但要注意是否丢失业务信息 - 若需聚合(如取右表最新一条),得先用
groupby().apply()或sort_values().drop_duplicates()预处理
join() 方法也能做 Left Join,但限制更多
DataFrame.join() 默认就是左连接,但它只基于索引合并,且右表必须是 DataFrame 或 Series,不能像 merge() 那样灵活指定任意列。适合“左表带索引、右表也按同样索引组织”的场景。
容易踩的坑是:调用 df_left.join(df_right) 时,如果 df_right 没设索引,会报 AttributeError: 'DataFrame' object has no attribute 'index'(其实是它没默认索引列,不是真没 index)。
- 安全写法:
df_left.join(df_right.set_index('id'), on='id'),但这时其实不如直接用merge() -
join()不支持left_on/right_on,也不支持多列 join,扩展性差 - 性能上,索引 join 在大数据量时可能略快,但可读性和调试成本高,日常推荐统一用
merge()
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











