关键在于统一读取逻辑而非简单拼接:需用glob批量获取路径,显式指定header、skiprows、usecols;concat时设ignore_index=True和sort=False;用keys/names标记来源;大文件分块读取避免内存溢出。

用 pd.concat() 合并多个 Excel 表格前,先统一读取逻辑
直接对每个文件调用 pd.read_excel() 再塞进 pd.concat() 是可行的,但容易因表头不一致、空行、sheet 名称不同出错。关键不是“怎么拼”,而是“怎么读得干净”。
实操建议:
- 用
glob.glob("*.xlsx")或pathlib.Path().glob("*.xlsx")批量获取路径,避免手动列文件名 - 统一指定
header=0(显式声明首行为列名),避免某些表第一行是标题、某些是空行导致列数错位 - 加
skiprows=0显式控制跳过行数,防止部分文件顶部有合并单元格或说明文字 - 若所有表结构一致,优先用
usecols限定列范围(如usecols="A:C"或usecols=[0,1,2]),跳过格式列、备注列等干扰项
合并时必须处理 ignore_index=True 和 sort=False
默认 pd.concat() 会保留各 DataFrame 原始索引,导致最终结果索引重复、跳跃、非连续——后续用 .iloc 或导出到 Excel 时容易误判行号。
常见错误现象:ValueError: Plan shapes are not aligned(实际常因列名大小写/空格不一致触发,但索引混乱会让调试更难)
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 强制加
ignore_index=True,让合并后索引从 0 重新编号 - 如果原始表格列顺序不完全一致(比如有的是
["name", "score"],有的是["score", "name"]),必须加sort=False,否则 pandas 会自动按字母序重排列,导致数据错列 - 不要依赖默认的
sort=True,它在列名含中文、特殊字符或大小写混用时行为不可控
遇到列名不一致?别急着 rename,先用 keys 和 names 标记来源
上百个文件里总有几个表头手输错了:比如 “销售额” vs “销售金额”、“客户ID” vs “cust_id”。硬统一列名容易漏改、误改,且丢失溯源信息。
实操建议:
- 把每个 DataFrame 包装成列表时,同时记录文件名或 sheet 名,例如:
[df.assign(source=f.name) for f in files] - 或者用
pd.concat(..., keys=file_names, names=["source_file"]),生成多级索引,方便后续按来源筛选、对比差异 - 真正需要对齐字段时,再用
map或replace做轻量映射,而不是在读取阶段就暴力rename - 检查列名一致性可用:
set.union(*[set(df.columns) for df in dfs])快速看全集,再逐个比对缺失项
pd.concat() 卡住或内存爆掉?换 chunksize + 迭代合并
单个 Excel 文件本身不大,但几百个加起来可能超 2GB,pd.concat() 默认把全部 DataFrame 加载进内存再拼接,极易触发 MemoryError 或响应停滞。
实操建议:
- 不一次性读完所有文件,改用生成器分批处理:每次读 20 个 →
concat→ 保存中间结果(如to_parquet)→ 清空变量 → 继续下一批 - 对单个大 Excel,用
pd.read_excel(..., chunksize=5000)分块读,再对每块做concat,避免单文件加载失败 - 避免用
append=True往已有 DataFrame 上反复追加(已弃用且极慢),坚持“批量读 → 一次 concat → 一次写入”流式逻辑
合并数百个表不是拼速度,是拼鲁棒性。最常被忽略的是:没验证前 3 个文件是否真能对齐,就直接跑全量——结果卡在第 297 个文件报错,而错误信息只说“列数不匹配”,根本看不出是哪个文件哪一列出了问题。


















