Python实现Excel数据高效比对与清洗

📅 发布时间:2026/8/4 15:13:34
Python实现Excel数据高效比对与清洗
1. 问题场景与需求分析在日常HR管理或行政工作中我们经常需要处理来自不同系统的员工数据。比如考勤系统导出的当月在职人员名单财务系统提供的工资发放清单部门自行维护的项目组成员表这些数据通常以Excel工作表形式存在但往往存在以下痛点各系统间员工ID格式不统一如有的带前缀有的纯数字姓名可能存在简繁体/大小写差异部分字段可能包含多余空格等隐形字符需要直观展示比对结果供非技术人员查阅实际案例某公司年终审计时发现考勤系统显示在职员工比HR系统多出12人经查是离职员工未及时同步导致五险一金多缴造成直接经济损失8万余元。2. 技术方案选型2.1 为什么选择Python相比Excel自带函数或VBAPython处理该任务的优势在于处理大文件更高效实测10万行数据Python比VBA快3倍以上更灵活的数据清洗能力正则表达式、字符串处理等丰富的可视化选项条件格式、差异高亮等可保存为模板脚本重复使用2.2 核心工具栈import pandas as pd # 数据操作 from openpyxl import load_workbook # Excel编辑 from openpyxl.styles import PatternFill # 单元格样式 import difflib # 模糊匹配3. 完整实现步骤3.1 数据预处理def clean_data(df): # 统一字符串格式 df df.apply(lambda x: x.str.strip() if x.dtype object else x) # 处理空值 df.fillna(NULL_PLACEHOLDER, inplaceTrue) # 统一ID格式示例去除前缀 df[员工ID] df[员工ID].str.replace(EMP-, ) return df # 读取两个工作表 df1 pd.read_excel(data.xlsx, sheet_nameSheet1) df2 pd.read_excel(data.xlsx, sheet_nameSheet2) # 清洗数据 df1_clean clean_data(df1) df2_clean clean_data(df2)3.2 关键比对逻辑3.2.1 精确匹配推荐方案# 使用merge进行比对 result pd.merge( df1_clean, df2_clean, on[员工ID, 姓名], # 关键字段 howouter, indicatorTrue ) # 分类结果 matched result[result[_merge] both] only_in_df1 result[result[_merge] left_only] only_in_df2 result[result[_merge] right_only]3.2.2 模糊匹配备选方案当姓名可能存在拼写差异时def fuzzy_match(row): # 使用difflib计算相似度 return difflib.SequenceMatcher( None, str(row[姓名_x]), str(row[姓名_y]) ).ratio() # 应用模糊匹配 fuzzy_results result.apply(fuzzy_match, axis1) result[相似度] fuzzy_results3.3 可视化输出def highlight_diff(sheet): # 设置差异高亮样式 red_fill PatternFill(start_colorFFEE1111, end_colorFFEE1111, fill_typesolid) green_fill PatternFill(start_colorFF11EE11, end_colorFF11EE11, fill_typesolid) # 遍历单元格标记差异 for row in sheet.iter_rows(): for cell in row: if DIFF_FLAG in str(cell.value): cell.fill red_fill elif NEW_FLAG in str(cell.value): cell.fill green_fill # 保存结果到新Excel with pd.ExcelWriter(comparison_result.xlsx) as writer: matched.to_excel(writer, sheet_name匹配成功, indexFalse) only_in_df1.to_excel(writer, sheet_name仅表1存在, indexFalse) only_in_df2.to_excel(writer, sheet_name仅表2存在, indexFalse) # 应用高亮样式 wb load_workbook(comparison_result.xlsx) for sheetname in wb.sheetnames: highlight_diff(wb[sheetname]) wb.save(comparison_result_final.xlsx)4. 实战经验与避坑指南4.1 性能优化技巧大文件处理方案# 分块读取适用于超大型文件 chunk_size 10000 reader pd.read_excel(large_file.xlsx, chunksizechunk_size) for chunk in reader: process(chunk) # 自定义处理函数内存优化参数pd.read_excel( data.xlsx, dtype{员工ID: string, 部门: category}, # 指定数据类型 usecols[员工ID, 姓名, 部门] # 只读取必要列 )4.2 常见问题排查问题1编码错误导致乱码# 指定编码格式常见于包含中文的Excel df pd.read_excel(data.xlsx, engineopenpyxl, encodinggbk)问题2日期格式不一致# 统一日期格式 df[入职日期] pd.to_datetime(df[入职日期], errorscoerce).dt.strftime(%Y-%m-%d)问题3隐藏字符干扰# 彻底清洗不可见字符 import re df[姓名] df[姓名].apply(lambda x: re.sub(r[\x00-\x1F\x7F], , str(x)))5. 扩展应用场景5.1 多表联合比对# 比对三个及以上工作表 from functools import reduce dfs [df1, df2, df3] common_cols list(reduce(lambda x, y: x.intersection(y), [set(df.columns) for df in dfs])) result reduce(lambda left,right: pd.merge(left, right, oncommon_cols, howouter), dfs)5.2 自动化邮件报告import smtplib from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders msg MIMEMultipart() msg[Subject] 员工数据比对报告 msg.attach(MIMEBase(application, octet-stream).set_payload(open(comparison_result_final.xlsx, rb).read())) encoders.encode_base64(msg.get_payload(0)) msg.get_payload(0).add_header(Content-Disposition, attachment, filenameresult.xlsx) with smtplib.SMTP(smtp.example.com) as server: server.sendmail(senderexample.com, receiverexample.com, msg.as_string())5.3 数据库集成方案# 从数据库直接读取比对 import sqlalchemy engine sqlalchemy.create_engine(postgresql://user:passlocalhost:5432/hr_db) df_db pd.read_sql(SELECT * FROM employees, engine) df_excel pd.read_excel(current.xlsx) pd.merge(df_db, df_excel, onemployee_id, howouter)