pandas导出带多级列索引的DataFrame到Excel时如何去除行索引
问题说明
pandas导出DataFrame为CSV/Excel文件时,默认会在首列写入行索引,常规场景下传入index=False参数即可关闭行索引导出。但当DataFrame使用多级列索引(MultiIndex columns)时,低版本pandas会直接抛出如下报错:
NotImplementedError: Writing to Excel with MultiIndex columns and no index ('index'=False) is not yet implemented.
测试用示例代码:
import pandas as pd import numpy as np col = pd.MultiIndex.from_arrays([['one', 'one', 'one', 'two', 'two', 'two'], ['a', 'b', 'c', 'a', 'b', 'c']]) data = pd.DataFrame(np.random.randn(4, 6), columns=col) data.to_excel('test.xlsx')
默认导出的文件会存在首列多余行索引、表头区域错位、表头和数据之间多空行的问题,目标是保留原多级列名结构,删除整列行索引,清理错位的多余内容。
注:如果是导出CSV格式,所有pandas版本都原生支持多级列索引+
index=False的组合,不会抛出上述报错,直接使用即可。
可用方案
方案1:升级pandas(最简便)
pandas 1.4.0及以上正式版本已经修复了这个bug,直接传入index=False即可正常导出,不需要额外处理:
# pandas版本 >=1.4.0 可用 data.to_excel('test_fixed.xlsx', index=False)
导出的文件会自动对齐多级表头,无多余行索引列,也不会出现错位、空行问题。
方案2:导出后用openpyxl轻量后处理(兼容低版本pandas)
如果环境无法升级pandas,可以先按默认逻辑导出文件,再通过openpyxl加载文件做简单修正即可,原有多级表头的合并结构会完整保留:
from openpyxl import load_workbook # 先按默认参数导出文件 data.to_excel('test_fixed.xlsx') # 加载文件做后处理 wb = load_workbook('test_fixed.xlsx') ws = wb.active # 删除第1列(存放行索引的A列) ws.delete_cols(1) # 检查第三行如果全为空(老版本pandas导出生成的多余空行),就删除这行 if all([cell.value is None for cell in ws[3]]): ws.delete_rows(3, 1) wb.save('test_fixed.xlsx')
这个方案改动量极小,导出效果和pandas新版本原生导出完全一致。
方案3:手动写入内容(完全可控,无兼容问题)
如果需要完全规避pandas导出逻辑的bug,可以手动构造表头、写入数据,灵活度最高:
from openpyxl import Workbook wb = Workbook() ws = wb.active # 逐行写入多级表头 ws.append(col.get_level_values(0).tolist()) # 写入第一级列名 ws.append(col.get_level_values(1).tolist()) # 写入第二级列名 # 写入所有数据行,跳过行索引 for row in data.itertuples(index=False, name=None): ws.append(row) # 合并第一级表头的相同单元格,还原pandas默认的合并展示效果 ws.merge_cells('A1:C1') # 对应列名"one"的合并区域 ws.merge_cells('D1:F1') # 对应列名"two"的合并区域 wb.save('test_fixed.xlsx')
这个方案不依赖pandas的Excel导出逻辑,所有版本都能正常运行,还可以按需自定义表头样式、单元格格式。
内容的提问来源于stack exchange,提问作者wen tse yang

