我正在处理一组几乎有 60 列的数据(文本/地址/数字)。使用 Pandas 处理数据后,我必须将其导出为
xlsx
格式。
这就是我生成输出的方式:
with pd.ExcelWriter("output.xlsx", engine='xlsxwriter') as writer:
df.to_excel(writer, sheet_name="sheet", index=False)
这个方法我也试过:
df.to_excel('output.xlsx', index=False, engine='xlsxwriter')
我注意到,生成
xlsx
比像 csv
这样的格式要慢得多。并且随着记录数量的增加,生成 xlsx
文件的时间显着增加。
这是
.to_excel
的正常预期行为还是有问题?有没有办法调试并解决这个问题?
我必须能够在几秒钟内生成约 300K 到约 600K 记录的
xlsx
文件,但如您所见,我需要大约 6 分钟才能生成约 500K 记录的 excel 文件。
我用来生成这些文件的硬件有 16 核 CPU 和 64 GB 内存。
我找到了一个稍微快一点的解决方案,比仅仅使用
engine='xlsxwriter'
import pandas as pd
from xlsxwriter.workbook import Workbook
def export_excel(df: pd.DataFrame, file_path_out: str):
workbook = Workbook(file_path_out)
worksheet = workbook.add_worksheet()
worksheet.write_row(0, 0, [col for col in df.columns])
for index, row in df.iterrows():
worksheet.write_row(index+1, 0, [col for col in row])
workbook.close()
下表显示了三种方法对于 100 到 50k 行随机数据(60 列)的运行时间。测量的时间以秒为单位。 openpyxl 和 xlsxwriter 是 df.export_excel(engine=...) 调用,export_excel 是我建议的代码,上面。它不是游戏规则改变者......但它更快
row count: openpyxl, xlsxwriter, export_excel
100: 0.1272597312927246, 0.15707993507385254, 0.12616825103759766
1000: 1.1917698383331299, 0.8460557460784912, 0.7760021686553955
10000: 12.29027795791626, 8.1415114402771, 6.129252195358276
25000: 32.34258818626404, 23.32529616355896, 18.124294996261597
50000: 63.35693168640137, 40.77235984802246, 30.406764268875122
使用
workbook = Workbook(file_path_out, {'constant_memory': True})
会进一步提高运行时间(但不是很多:25k 行快 1 秒=
pandas.DataFrame.to_excel
文档engine
值可能是openpyxl
或xlsxwriter
,当您使用后一个时,我建议测试engine='openpyxl'
与engine='xlsxwriter'
。
我找到了一种更快的方法,在 1alkh+ 行上进行测试(用于从 json(字典列表)创建 excel)。
def json_to_excel(self):
"""
Converts a list of dictionaries (JSON data) to an Excel file (.xlsx).
Output- str: Excel datafram (.xlsx).
"""
workbook = Workbook()
headers = list(self.data[0].keys()) if self.data else []
values = [headers] + [[item[key] for key in headers] for item in self.data]
workbook.new_sheet(self.sheet_name or "Sheet 1", data=values)
output = io.BytesIO()
workbook.save(output)
return output.getvalue()