订单表合并客户表后行数变多,先检查客户表的关联键是否重复。用 validate="many_to_one" 声明多笔订单可以对应同一客户,但客户表中的键必须唯一。

用一组数据复现行数膨胀
保存为 merge_demo.py。订单编号 1 和 2 都属于客户 A,而客户表意外出现两个 A。
import pandas as pd
orders = pd.DataFrame({"order_id": [1, 2, 3], "customer_id": ["A", "A", "Z"]})
customers = pd.DataFrame({"customer_id": ["A", "A", "B"],
"name": ["Alice", "Alicia", "Bob"]})
print(len(orders.merge(customers, on="customer_id", how="left")))
预期得到 5 行。每笔 A 的订单都与右表两条记录匹配。
找出重复并让错误尽早暴露
追加以下代码,显示右表中参与重复的所有行。
duplicates = customers[customers.duplicated("customer_id", keep=False)]
print(duplicates)
try:
orders.merge(customers, on="customer_id", how="left", validate="many_to_one")
except pd.errors.MergeError:
print("客户键重复")应看到两条 A 和一条错误提示。实际数据需要按业务确认保留哪条记录。
修正后再查看未匹配的订单
示例明确使用 Alice 作为客户 A 的有效记录。
verified = pd.DataFrame({"customer_id": ["A", "B"], "name": ["Alice", "Bob"]})
result = orders.merge(verified, on="customer_id", how="left",
validate="many_to_one", indicator=True)
assert len(result) == len(orders)
print(result.loc[result["_merge"].eq("left_only"), "order_id"].tolist())预期得到 [3]。如果业务不允许空键,应在合并前检查缺失键,因为 pandas 可能把两边的空键匹配起来。

















