
本文介绍如何通过pandas的merge操作精准识别两份客户数据中,以cust_id为键、town_id为追踪字段时发生变更的所有记录,并生成结构清晰的对比结果dataframe。
在数据分析和ETL流程中,常需比对两个时间点(如月初/月末、版本v1/v2)的客户主数据,快速定位关键字段(如所属区域town_id)是否发生变化。核心思路是:以主键(cust_id)为纽带合并两个DataFrame,再筛选出关联行中目标字段(town_id)值不一致的记录。
具体实现分三步:
- 内连接(inner join)对齐共同客户:使用 df1.merge(df2, on="cust_id", how="inner") 确保只保留两个表中均存在的 cust_id,避免新增或流失客户干扰变更判断;
- 添加后缀区分来源字段:通过 suffixes=["_initial", "_latter"] 明确标识来自 df1 和 df2 的 town_id,得到 town_id_initial 和 town_id_latter;
- 布尔索引筛选变更行:out.town_id_initial != out.town_id_latter 直接过滤出 town_id 发生变化的记录;
- 整理输出结构:选取所需列(含原始name字段),并重命名 name_initial 为 name 以保持语义清晰。
完整代码如下:
import pandas as pd
# 示例数据
df1 = pd.DataFrame({
'name': ['cxa', 'cxb', 'cxc', 'cxd'],
'cust_id': ['c1001', 'c1002', 'c1003', 'c1004'],
'town_id': ['t001', 't001', 't001', 't002']
})
df2 = pd.DataFrame({
'name': ['cxa', 'cxb', 'cxd', 'cxe', 'cxf'],
'cust_id': ['c1001', 'c1002', 'c1004', 'c1005', 'c1006'],
'town_id': ['t002', 't001', 't001', 't001', 't001']
})
# 执行变更检测
merged = df1.merge(df2, on="cust_id", how="inner", suffixes=("_initial", "_latter"))
changed = merged[merged["town_id_initial"] != merged["town_id_latter"]]
result = changed[["name_initial", "cust_id", "town_id_initial", "town_id_latter"]].rename(
columns={"name_initial": "name"}
)
print(result)输出结果:
name cust_id town_id_initial town_id_latter 0 cxa c1001 t001 t002 2 cxd c1004 t002 t001
⚠️ 注意事项:
- 若需包含仅存在于某一方的客户(如新注册或已注销),应改用 how="outer" 并配合 pd.isna() 判断缺失,但此时“变更”逻辑需重新定义;
- 确保 cust_id 在各自DataFrame中无重复,否则 merge 会产生笛卡尔积,导致误判;
- 对于多字段联合变更检测(如 town_id + status 同时变),可扩展布尔条件:(... & (df.town_id_initial != df.town_id_latter));
- 大数据量时建议提前对 cust_id 列设置索引或使用 pd.concat([df1, df2], keys=['old','new']) 配合 groupby 实现更高效对比。
该方法简洁、可读性强,是Pandas中处理键值变更分析的标准实践。










