比较两个excel文件的指定列是否一致
import pandas as pd
import os
from typing import Tuple, Dict, List
import warnings
warnings.filterwarnings('ignore')def validate_file_and_columns(file_path: str, key_col: str, compare_cols: List[str]) -> Tuple[pd.DataFrame, bool]:"""验证文件是否存在以及指定列是否存在:param file_path: Excel文件路径:param key_col: 检索列(用于匹配行的列):param compare_cols: 要比较的目标列列表:return: DataFrame和验证结果(True/False)"""# 验证文件是否存在if not os.path.exists(file_path):print(f"错误:文件 {file_path} 不存在!")return pd.DataFrame(), False# 读取Excel文件try:df = pd.read_excel(file_path)except Exception as e:print(f"错误:读取文件 {file_path} 失败 - {str(e)}")return pd.DataFrame(), False# 验证检索列是否存在all_cols = df.columns.tolist()if key_col not in all_cols:print(f"错误:文件 {file_path} 中不存在检索列 '{key_col}'")print(f"该文件包含的列:{all_cols}")return pd.DataFrame(), False# 验证所有比较列是否存在missing_cols = [col for col in compare_cols if col not in all_cols]if missing_cols:print(f"错误:文件 {file_path} 中缺少以下比较列:{missing_cols}")print(f"该文件包含的列:{all_cols}")return pd.DataFrame(), False# 检查检索列是否有重复值if df[key_col].duplicated().any():duplicate_values = df[df[key_col].duplicated(keep=False)][key_col].unique()print(f"警告:文件 {file_path} 的检索列 '{key_col}' 存在重复值:{duplicate_values[:5]}...")return df, Truedef compare_excel_columns(file1_path: str,file2_path: str,key_col: str,compare_cols: List[str],output_result: bool = True,output_path: str = "comparison_result.xlsx"
) -> Dict[str, List]:"""比较两个Excel文件的指定列:param file1_path: 第一个Excel文件路径:param file2_path: 第二个Excel文件路径:param key_col: 检索列(用于匹配行的列):param compare_cols: 要比较的目标列列表:param output_result: 是否保存比较结果到Excel:param output_path: 结果文件保存路径:return: 比较结果字典"""print("="*50)print("开始比较Excel文件...")print(f"文件1:{file1_path}")print(f"文件2:{file2_path}")print(f"检索列:{key_col}")print(f"比较列:{compare_cols}")print("="*50)# 验证并读取两个文件df1, df1_valid = validate_file_and_columns(file1_path, key_col, compare_cols)df2, df2_valid = validate_file_and_columns(file2_path, key_col, compare_cols)if not df1_valid or not df2_valid:print("文件验证失败,终止比较!")return {"error": "文件验证失败"}# 以检索列为索引,方便匹配df1_indexed = df1.set_index(key_col)df2_indexed = df2.set_index(key_col)# 获取所有检索键keys1 = set(df1_indexed.index)keys2 = set(df2_indexed.index)# 分析键的匹配情况common_keys = sorted(keys1 & keys2) # 共同存在的键(用于比较)only_in_file1 = sorted(keys1 - keys2) # 只在文件1中存在的键only_in_file2 = sorted(keys2 - keys1) # 只在文件2中存在的键print(f"\n检索列匹配情况:")print(f"共同存在的记录数:{len(common_keys)}")print(f"仅文件1存在的记录数:{len(only_in_file1)}")print(f"仅文件2存在的记录数:{len(only_in_file2)}")# 比较共同键的目标列match_results = []mismatch_results = []print(f"\n正在比较 {len(common_keys)} 条共同记录...")for key in common_keys:row1 = df1_indexed.loc[key]row2 = df2_indexed.loc[key]row_result = {key_col: key}is_mismatch = Falsefor col in compare_cols:val1 = row1[col]val2 = row2[col]# 处理NaN值的比较(NaN == NaN 结果为False,这里视为相等)if pd.isna(val1) and pd.isna(val2):match_status = "一致"elif pd.isna(val1) or pd.isna(val2):match_status = "不一致"is_mismatch = Trueelif str(val1) == str(val2): # 转为字符串比较,避免数值类型差异(如int和float)match_status = "一致"else:match_status = "不一致"is_mismatch = Truerow_result[f"{col}_文件1"] = val1row_result[f"{col}_文件2"] = val2row_result[f"{col}_比较结果"] = match_statusif is_mismatch:mismatch_results.append(row_result)else:match_results.append(row_result)# 统计结果total_common = len(common_keys)match_count = len(match_results)mismatch_count = len(mismatch_results)print(f"\n比较结果统计:")print(f"完全一致的记录数:{match_count}")print(f"存在不一致的记录数:{mismatch_count}")print(f"一致率:{match_count/total_common*100:.2f}%" if total_common > 0 else "无共同记录可比较")# 整理最终结果final_results = {"共同记录_完全一致": match_results,"共同记录_存在不一致": mismatch_results,"仅文件1存在的记录": [{key_col: key} for key in only_in_file1],"仅文件2存在的记录": [{key_col: key} for key in only_in_file2],"统计信息": {"文件1总记录数": len(df1),"文件2总记录数": len(df2),"共同记录数": total_common,"完全一致记录数": match_count,"不一致记录数": mismatch_count,"仅文件1记录数": len(only_in_file1),"仅文件2记录数": len(only_in_file2),"一致率(%)": match_count/total_common*100 if total_common > 0 else 0}}# 保存结果到Excelif output_result:try:with pd.ExcelWriter(output_path, engine='openpyxl') as writer:# 写入各个结果表if match_results:pd.DataFrame(match_results).to_excel(writer, sheet_name="完全一致", index=False)if mismatch_results:pd.DataFrame(mismatch_results).to_excel(writer, sheet_name="存在不一致", index=False)if only_in_file1:pd.DataFrame(only_in_file1, columns=[key_col]).to_excel(writer, sheet_name="仅文件1存在", index=False)if only_in_file2:pd.DataFrame(only_in_file2, columns=[key_col]).to_excel(writer, sheet_name="仅文件2存在", index=False)# 写入统计信息stats_df = pd.DataFrame(final_results["统计信息"].items(), columns=["统计项", "数值"])stats_df.to_excel(writer, sheet_name="统计信息", index=False)print(f"\n比较结果已保存到:{output_path}")except Exception as e:print(f"警告:保存结果文件失败 - {str(e)}")print("\n" + "="*50)print("比较完成!")print("="*50)return final_results# ------------------- 示例使用 -------------------
if __name__ == "__main__":# 配置参数(请根据实际需求修改)FILE1_PATH = "file1.xlsx" # 第一个Excel文件路径FILE2_PATH = "file2.xlsx" # 第二个Excel文件路径KEY_COLUMN = "ID" # 检索列(用于匹配行的唯一标识列)COMPARE_COLUMNS = ["姓名", "年龄", "成绩"] # 要比较的目标列列表OUTPUT_PATH = "comparison_result.xlsx" # 结果输出路径# 执行比较results = compare_excel_columns(file1_path=FILE1_PATH,file2_path=FILE2_PATH,key_col=KEY_COLUMN,compare_cols=COMPARE_COLUMNS,output_result=True,output_path=OUTPUT_PATH)代码核心功能说明:
文件验证:
- 检查文件是否存在
- 验证检索列和比较列是否存在于两个文件中
- 检测检索列是否有重复值(避免一对多匹配问题)
行匹配逻辑:
- 以指定的「检索列」(如 ID)作为唯一标识,匹配两个文件中的对应行
- 自动识别三种情况:共同存在的行、仅在文件 1 存在的行、仅在文件 2 存在的行
值比较规则:
- 支持多列同时比较
- 处理 NaN / 空值(两个空值视为一致)
- 转为字符串比较,避免数值类型差异(如 100 和 100.0 视为一致)
- 详细记录每列的比较结果
结果输出:
- 控制台显示统计信息(匹配率、各类记录数)
- 生成 Excel 结果文件,包含 5 个工作表:
- 完全一致:所有比较列都匹配的记录
- 存在不一致:至少有一列不匹配的记录(显示具体差异)
- 仅文件 1 存在:只在第一个文件中出现的记录
- 仅文件 2 存在:只在第二个文件中出现的记录
- 统计信息:详细的数量统计
使用方法:
安装依赖:
bash
pip install pandas openpyxl修改配置参数:
FILE1_PATH和FILE2_PATH:改为你的两个 Excel 文件路径KEY_COLUMN:改为用于匹配行的列名(如 ID、编号等唯一标识)COMPARE_COLUMNS:改为需要比较的列名列表(可多个)OUTPUT_PATH:结果文件保存路径(默认即可)
运行代码:
- 直接运行脚本,会自动完成比较并生成结果文件
注意事项:
- 检索列建议使用唯一标识(如 ID),避免重复值导致匹配混乱
- 支持.xlsx 和.xls 格式(.xls 需要额外安装 xlrd 库:
pip install xlrd==1.2.0) - 对于日期类型,会转为字符串比较(确保两个文件的日期格式一致)
- 结果文件会覆盖同名文件,请确保输出路径正确
