Python实现Excel多表自动VLOOKUP关联匹配
作者:小庄-Python办公
场景引入
你手里有两份数据:
- 表 A:员工基础信息表(工号、姓名、部门)—— 1000 行
- 表 B:绩效考核表(工号、评分、等级)—— 800 行
领导要求把两份数据合并,通过"工号"关联,得到一份包含姓名、部门和绩效的完整报表。在 Excel 中,你需要手动写 VLOOKUP 公式、拖拽填充,数据量一大就容易卡死。
本节教你用 Python 的 merge 操作,一行代码完成多表关联,效率是 Excel 的 100 倍以上。
技术原理
VLOOKUP 的本质就是数据库中的 JOIN 操作。pandas 提供了 merge() 函数,功能比 VLOOKUP 更强大:
表A(员工信息) 表B(绩效信息)
工号 | 姓名 | 部门 工号 | 评分 | 等级
001 | 张三 | 技术部 001 | 90 | A
002 | 李四 | 财务部 003 | 85 | B
003 | 王五 | 人事部 005 | 78 | C
↓ merge(on='工号')
结果表
工号 | 姓名 | 部门 | 评分 | 等级
001 | 张三 | 技术部 | 90 | A
002 | 李四 | 财务部 | NaN | NaN ← 表B中没有该工号
003 | 王五 | 人事部 | 85 | B
关联方式对比
| 关联方式 | merge 参数 | 说明 | SQL 等价 |
|---|---|---|---|
| 左连接 | how='left' | 保留左表全部,右表匹配不到的填 NaN | LEFT JOIN |
| 右连接 | how='right' | 保留右表全部 | RIGHT JOIN |
| 内连接 | how='inner' | 只保留两边都有的 | INNER JOIN |
| 外连接 | how='outer' | 保留所有记录 | FULL OUTER JOIN |
环境准备
pip install pandas openpyxl
完整代码
import pandas as pd
def auto_vlookup(main_file, lookup_file, main_key, lookup_key, lookup_columns, output_file="关联结果.xlsx", how='left'):
"""
Python 版 VLOOKUP 自动关联两个 Excel 表
参数:
main_file: 主表文件路径(保留此表的全部数据)
lookup_file: 被查找的表文件路径
main_key: 主表中用于匹配的列名
lookup_key: 查找表中用于匹配的列名
lookup_columns: 需要从查找表中提取的列名列表,如 ['评分', '等级']
output_file: 输出文件名
how: 关联方式,'left'/'inner'/'right'/'outer'
"""
# 1. 读取两个表
main_df = pd.read_excel(main_file, engine='openpyxl')
lookup_df = pd.read_excel(lookup_file, engine='openpyxl')
print(f"主表: {len(main_df)} 行 × {len(main_df.columns)} 列")
print(f"查找表: {len(lookup_df)} 行 × {len(lookup_df.columns)} 列")
# 2. 验证列名是否存在
for col in [main_key, lookup_key] + lookup_columns:
if col not in main_df.columns and col not in lookup_df.columns:
print(f"错误: 列 '{col}' 在两个表中都不存在!")
return
# 3. 从查找表中只保留需要的列
select_columns = [lookup_key] + lookup_columns
lookup_subset = lookup_df[select_columns]
# 4. 执行关联(一行代码完成 VLOOKUP!)
result = pd.merge(
main_df,
lookup_subset,
left_on=main_key,
right_on=lookup_key,
how=how
)
# 5. 如果关联列名不同,删除重复的查找列
if main_key != lookup_key:
result.drop(columns=[lookup_key], inplace=True)
# 6. 统计匹配情况
matched = result[lookup_columns[0]].notna().sum()
unmatched = len(result) - matched
print(f"\n匹配结果: {matched} 行匹配成功, {unmatched} 行未匹配")
# 7. 导出结果
result.to_excel(output_file, index=False, engine='openpyxl')
print(f"结果已保存: {output_file} ({len(result)} 行)")
return result
# ==================== 多表关联 ====================
def multi_table_vlookup(base_file, lookup_files, key_column, output_file="多表关联结果.xlsx"):
"""
一个主表关联多个查找表
参数:
base_file: 主表路径
lookup_files: 列表,每个元素为 {'file': '文件路径', 'key': '匹配列', 'columns': ['需要提取的列']}
key_column: 主表的匹配列名
output_file: 输出文件
"""
result = pd.read_excel(base_file, engine='openpyxl')
print(f"主表: {len(result)} 行")
for lookup_info in lookup_files:
lookup_df = pd.read_excel(lookup_info['file'], engine='openpyxl')
select_cols = [lookup_info['key']] + lookup_info['columns']
lookup_subset = lookup_df[[c for c in select_cols if c in lookup_df.columns]]
result = pd.merge(
result,
lookup_subset,
left_on=key_column,
right_on=lookup_info['key'],
how='left'
)
if key_column != lookup_info['key']:
result.drop(columns=[lookup_info['key']], inplace=True)
print(f"已关联 {lookup_info['file']}")
result.to_excel(output_file, index=False, engine='openpyxl')
print(f"\n多表关联完成: {output_file}")
# ==================== 使用示例 ====================
if __name__ == "__main__":
# ========== 示例 1:关联员工绩效 ==========
auto_vlookup(
main_file="员工信息表.xlsx",
lookup_file="绩效考核表.xlsx",
main_key="工号",
lookup_key="工号",
lookup_columns=["评分", "等级"],
output_file="员工完整信息表.xlsx",
how='left' # 保留所有员工,没有绩效的显示 NaN
)
# ========== 示例 2:多表关联 ==========
# multi_table_vlookup(
# base_file="员工信息表.xlsx",
# lookup_files=[
# {'file': '绩效考核表.xlsx', 'key': '工号', 'columns': ['评分', '等级']},
# {'file': '薪资表.xlsx', 'key': '工号', 'columns': ['基本工资', '绩效奖']},
# {'file': '培训记录表.xlsx', 'key': '工号', 'columns': ['培训课程', '学时']},
# ],
# key_column="工号",
# output_file="员工全景档案表.xlsx"
# )
代码逐行解析
1. 核心关联函数
result = pd.merge(main_df, lookup_subset, left_on=main_key, right_on=lookup_key, how='left')
这行代码等价于 Excel 中的:
=VLOOKUP(A2, 查找表!A:C, 2, FALSE)
但 pandas 的 merge 有几个优势:
- 不需要手动指定列序号(Excel 中经常数错列导致取错数据)
- 可以一次关联多列(Excel 需要写多个 VLOOKUP 公式)
- 支持多种关联方式(VLOOKUP 只能做左连接)
2. 只提取需要的列
select_columns = [lookup_key] + lookup_columns lookup_subset = lookup_df[select_columns]
先筛选出需要的列,再做关联,避免引入不必要的字段。
3. 匹配统计
matched = result[lookup_columns[0]].notna().sum() unmatched = len(result) - matched
notna():判断值是否不为 NaN(即匹配成功)sum():统计 True 的数量
进阶技巧
技巧 1:模糊匹配(容差关联)
如果工号格式不一致(如 “001” vs “1”),需要先统一格式:
# 统一为字符串并补零 main_df['工号'] = main_df['工号'].astype(str).str.zfill(3) lookup_df['工号'] = lookup_df['工号'].astype(str).str.zfill(3)
技巧 2:多列联合关联
如果需要通过多个字段联合匹配(如"姓名"+"部门"同时匹配):
result = pd.merge(
main_df, lookup_df,
left_on=['姓名', '部门'],
right_on=['姓名', '部门'],
how='left'
)
技巧 3:处理重复值
如果查找表中有重复的匹配键,merge 会产生笛卡尔积(行数暴增):
# 查找表去重(保留第一条) lookup_df.drop_duplicates(subset=['工号'], keep='first', inplace=True)
常见问题
Q1:关联后行数变多了?
原因:查找表中存在重复的匹配键值。
解决:
# 检查是否有重复 print(lookup_df['工号'].duplicated().sum()) # 去重后再关联 lookup_df = lookup_df.drop_duplicates(subset=['工号'], keep='first')
Q2:匹配结果全是 NaN?
原因:两表的匹配列数据类型不一致。比如一个是字符串 “001”,一个是数字 1。
解决:
# 统一转为字符串 main_df['工号'] = main_df['工号'].astype(str) lookup_df['工号'] = lookup_df['工号'].astype(str)
Q3:VLOOKUP 和 merge 的区别?
| 特性 | Excel VLOOKUP | pandas merge |
|---|---|---|
| 匹配方向 | 只能从左向右 | 任意方向 |
| 多列关联 | 需要辅助列 | 直接支持 |
| 关联方式 | 仅左连接 | 左/右/内/外 |
| 性能 | 大数据量卡顿 | 百万行秒级 |
总结
| 场景 | merge 参数 | 效果 |
|---|---|---|
| 保留主表全部 | how='left' | 类似 VLOOKUP |
| 只保留两边都有 | how='inner' | 交集 |
| 保留所有记录 | how='outer' | 并集 |
| 多列联合匹配 | left_on=[a,b] | 复合键关联 |
本节用 Python 一行 merge() 替代了 Excel 中繁琐的 VLOOKUP 公式,且功能更强大、性能更优。
到此这篇关于Python实现Excel多表自动VLOOKUP关联匹配的文章就介绍到这了,更多相关Python多表自动VLOOKUP关联匹配内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
