Pandas Merge & Join:像 SQL 一样稳妥地做连接
Updated on
做表连接最容易踩坑:键不对导致行数暴增或丢失,常见的是滥用 how=\"inner\",却很少用 validate、indicator 进行自检。
PAS 视角:
- 问题: 键错位让 merge 悄悄重复或遗漏数据。
- 激化: 排查重复后缀、意外的笛卡尔积或缺失行会耗费时间。
- 解决: 显式定义键,选择正确的
how,并用validate/indicator早发现问题。
Join 速查表
类型 (how) | 保留左表? | 保留右表? | 常见用途 |
|---|---|---|---|
inner | ✅ 仅匹配 | ✅ 仅匹配 | 交集 |
left | ✅ 全部 | 🚫 仅匹配 | 保留左表并补充 |
right | 🚫 仅匹配 | ✅ 全部 | 保留右表(少用,通常交换顺序即可) |
outer | ✅ 全部 | ✅ 全部 | 全连接,缺失填 NaN |
示例数据
import pandas as pd
orders = pd.DataFrame({
"order_id": [1, 2, 3],
"customer_id": [100, 101, 102],
"amount": [50, 80, 60],
})
customers = pd.DataFrame({
"customer_id": [100, 101, 103],
"name": ["Ada", "Ben", "Cara"],
"segment": ["pro", "basic", "pro"],
})基本列键 merge
result = orders.merge(
customers,
on="customer_id",
how="left",
validate="many_to_one", # 期望维表
indicator=True, # 审核覆盖
)validate捕捉意外的基数(many_to_many是警告信号)。indicator添加_merge列显示left_only/right_only/both。suffixes=("_order", "_cust")避免列名覆盖。
键名不同的连接
payments = pd.DataFrame({
"cust_id": [100, 100, 103],
"last_payment": ["2025-05-20", "2025-05-27", "2025-05-21"],
})
orders.merge(
payments,
left_on="customer_id",
right_on="cust_id",
how="left",
)基于索引的 join
customers_idx = customers.set_index("customer_id")
orders.join(customers_idx, on="customer_id", how="left")- 右表的键在索引里时
.join方便。 - 多级索引可用
on=["level_0", "level_1"]或先对齐索引。
处理重复与重叠
# Merge 前检查重复键
dupes = customers["customer_id"].value_counts()
problem_keys = dupes[dupes > 1]
# Merge 后检查意外膨胀
exploded = orders.merge(customers, on="customer_id", how="inner", validate="many_to_many")- 如果本该
many_to_one行数却增加,检查维表是否需drop_duplicates(subset=keys)。
一次合并多条指标
agg = (
orders.groupby("customer_id", as_index=False)
.agg(total_amount=("amount", "sum"), orders_count=("order_id", "count"))
)
customers.merge(agg, on="customer_id", how="left")先聚合再 merge,避免对原始交易表进行多次连接。
调试清单
| 症状 | 检查 |
|---|---|
| 行数暴增 | 查看 _merge;validate 设为期望的基数。 |
| Merge 后缺行 | 改用 how="left" 或 how="outer";对齐键的 dtype。 |
| 匹配错误 | 确保键的 dtype 相同(字符串 vs 整数)。 |
| 列名冲突 | 设置 suffixes 防止覆盖。 |
相关指南
关键要点
- 有目的地选择 join 类型;丰富数据时
left最安全。 - 用
validate、indicator、suffixes及早发现问题。 - 对齐键和值类型,必要时先去重维表以避免行数爆炸。