如何高效将pandas dataframe按内置文件名、工作表名导出为多Sheet Excel
pandas批量导出多文件多工作表的高效实现方案
需求说明
从pandas DataFrame批量生成导出文件,文件名、工作表名称均存储在原始数据中,支持生成多个导出文件,每个文件可包含多张工作表。
示例数据

现有实现的可优化点
- 变量重名:内层循环复用外层
grouped、name等变量,易引发逻辑异常 - CSV导出逻辑错误:错误将
ExcelWriter对象传入to_csv方法,无法正常生成CSV文件 - 终止逻辑不合理:单个文件命名非法就终止所有导出任务,不符合多文件导出预期
- 未兼容CSV多工作表场景:CSV不支持多工作表,同名CSV下的多个工作表会出现数据覆盖
- 重复计算:循环内重复执行列删除操作,可提前统一处理
优化实现
首先明确:分组导出的核心逻辑无法完全规避遍历分组,但可以通过优化计算逻辑、并行IO的方式大幅提升执行效率,尤其适合文件量较大的场景。
1. 优化串行版(无额外依赖,修正所有问题,执行效率高于原有实现)
import pandas as pd from pathlib import Path # 提前提取非分组列,避免循环内重复drop value_cols = [col for col in data.columns if col not in ["Filename", "Sheetname"]] # 按文件名分组 file_groups = data.groupby("Filename", as_index=False) for filename, file_df in file_groups: # 校验文件格式 suffix = Path(filename).suffix.lower() if suffix not in (".xlsx", ".csv"): print(f"跳过无效文件:{filename},仅支持xlsx和csv格式") continue # 按工作表名分组 sheet_groups = file_df.groupby("Sheetname", as_index=False) if suffix == ".xlsx": # 同一个Excel写入多个工作表 with pd.ExcelWriter(filename, engine="openpyxl") as writer: for sheet_name, sheet_df in sheet_groups: sheet_df[value_cols].to_excel(writer, sheet_name=sheet_name, index=False) else: # CSV不支持多工作表,每个工作表单独生成文件 for sheet_name, sheet_df in sheet_groups: # 多工作表时给CSV文件名加工作表后缀避免覆盖 csv_filename = f"{Path(filename).stem}_{sheet_name}{suffix}" if len(sheet_groups) > 1 else filename sheet_df[value_cols].to_csv(csv_filename, index=False)
2. 并行加速版(适合文件数≥10的场景,IO密集型场景效率可提升3~10倍)
利用多线程并行处理不同文件的导出任务,充分利用IO等待时间:
import pandas as pd from pathlib import Path from concurrent.futures import ThreadPoolExecutor, as_completed # 提前提取非分组列 value_cols = [col for col in data.columns if col not in ["Filename", "Sheetname"]] file_groups = data.groupby("Filename", as_index=False) def export_single_file(filename, file_df): suffix = Path(filename).suffix.lower() if suffix not in (".xlsx", ".csv"): return f"跳过无效文件:{filename}" sheet_groups = file_df.groupby("Sheetname", as_index=False) if suffix == ".xlsx": with pd.ExcelWriter(filename, engine="openpyxl") as writer: for sheet_name, sheet_df in sheet_groups: sheet_df[value_cols].to_excel(writer, sheet_name=sheet_name, index=False) else: for sheet_name, sheet_df in sheet_groups: csv_filename = f"{Path(filename).stem}_{sheet_name}{suffix}" if len(sheet_groups) > 1 else filename sheet_df[value_cols].to_csv(csv_filename, index=False) return f"导出完成:{filename}" # 最大线程数可根据实际情况调整,一般设置为5~20即可 with ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit(export_single_file, fname, f_df) for fname, f_df in file_groups] for future in as_completed(futures): print(future.result())
优化说明
- 提前统一计算需要保留的列,避免循环内重复执行drop操作,减少冗余计算
- 用上下文管理器
with处理文件写入对象,自动管理资源,无需手动调用save - 修正CSV导出逻辑,兼容多工作表场景,避免数据覆盖
- 单个文件导出失败不会影响其他文件,错误提示更清晰
- 并行版利用IO等待时间同时处理多个文件,文件量越大提升效果越明显
内容的提问来源于stack exchange,提问作者Esuriency
相关产品推荐
相关产品推荐

