我有一段非常简单的代码,其中有一组文件名,我需要打开每个文件名并提取一些数据以供以后使用。
for file in unique_file_names[1:]:
file_name = rootdir + "/" + str(file)
test_time = time.clock()
try:
wb_loop = load_workbook(file_name, read_only=True, data_only=True)
ws_loop = wb_loop["SHEET1"]
df = pd.DataFrame(ws_loop.values)
print("Opening Workbook: ", time.clock()-test_time)
newarray = np.vstack((newarray, df.loc[4:43,:13].values))
print("Data Manipulation: ", time.clock()-test_time)
因此,我尝试了几种不同的模块来读取excel文件,包括直接使用pandas.read_excel(),这是最佳方法,设法将工作簿打开时间为1.5-2s,并且堆叠需要花费0.03秒的时间。
我认为根据索引将数据分配到数组中的第三个维度可能会更快,但是我更专注于加快加载电子表格的时间,有什么建议吗?
编辑:我也确实创建了一个多线程池来尝试加快速度,但是由于某种原因,它开始使用15Gb内存并导致计算机崩溃
编辑2:
因此,最快的方法是按照公认的答案建议使用xlrd。我还意识到,在循环结束时删除工作簿更快。最终代码类似于
for file in unique_file_names[1:]:
file_name = rootdir + "/" + str(file)
test_time = time.clock()
try:
wb_loop = xlrd.open_workbook(file_name, on_demand = True)
ws_loop = wb_loop.sheet_by_name("Sheet1")
print("Opening Workbook: ", time.clock()-test_time)
df = pd.DataFrame([ws_loop.row_values(n) for n in range(ws_loop.nrows)])
newarray = np.vstack((newarray, df.loc[4:43,:13].values))
del wb_loop
print("Data Manipulation: ", time.clock()-test_time)
except:
pass
counter+=1
print("%s %% Done" %(counter*100/len(unique_file_names)))
wb_new = xlwt.Workbook()
ws_new = wb_new.add_sheet("Test")
ws_new.write(newarray)
wb_new.save(r"C:Libraries/Documents/NewOutput.xls")
这将输出每个循环平均时间1.6-1.8s。谢谢大家的帮助。
答案 0 :(得分:1)
这是一个快速基准测试(扩展this one)。显然,对于测试.xlsx文件,直接使用xlrd的速度要比熊猫快一些。如果.csv文件可用,则读取它们肯定会快得多,但使用LibreOffice进行转换则要慢得多:
pd_base 1.96 [in seconds]
pd_float 2.03
pd_object 2.01 [see cs95´s comment to your question]
pd_xlrd 1.95
pyxl_base 2.15
xlrd_base 1.79
csv_ready 0.17
csv_convert 18.72
代码如下:
import pandas as pd
import openpyxl
import xlrd
import subprocess
file = 'test.xlsx'
df = pd.DataFrame([[i+j for i in range(50)] for j in range(100)])
df.to_excel(file, index=False)
df.to_csv(file.replace('.xlsx', '.csv'), index=False)
def pd_base():
df = pd.read_excel(file)
def pd_float():
df = pd.read_excel(file, dtype=np.int)
def pd_object():
df = pd.read_excel(file, sheet_name="Sheet1", dtype=object)
def pd_xlrd():
df = pd.read_excel(file, engine='xlrd')
def pyxl_base():
wb = openpyxl.load_workbook(file, read_only=True, keep_links=False, data_only=True)
sh = wb.active
df = pd.DataFrame(sh.values)
def xlrd_base():
wb = xlrd.open_workbook(file)
sh = wb.sheet_by_index(0)
df = pd.DataFrame([sh.row_values(n) for n in range(sh.nrows)])
def csv_ready():
df = pd.read_csv(file.replace('.xlsx', '.csv'))
def csv_convert():
out = subprocess.check_output(['libreoffice --headless --convert-to csv test.xlsx'], shell=True, stderr=subprocess.STDOUT)
df = pd.read_csv(file.replace('.xlsx', '.csv'))
def measure(func, nums=50):
temp = time.time()
for num in range(nums):
func()
diff = time.time() - temp
print(func.__name__, '%.2f' % diff)
for func in [pd_base, pd_float, pd_object, pd_xlrd, pyxl_base, xlrd_base, csv_ready, csv_convert]:
measure(func)
答案 1 :(得分:0)
两个提示:
如果不提供类型,则大多数库将使用可能的最大值(64位)。如果即使在控制类型之后,您的数据也无法容纳在内存中,您就需要考虑分区并溢出到磁盘上。
下面是通过Executor接口编写的用于控制数据类型的代码示例
from concurrent.futures import ProcessPoolExecutor
from openpyxl import load_workbook
import pandas as pd
import numpy as np
def load_single(file):
file_name = rootdir + "/" + str(file)
wb_loop = load_workbook(file_name, read_only=True, data_only=True)
ws_loop = wb_loop["SHEET1"]
df = pd.DataFrame(ws_loop.values)
partial_array = df.loc[4:43, :13].values.astype(np.float32)
return partial_array
def run():
executor = ProcessPoolExecutor(max_workers=4)
files = unique_file_names[1:]
results = executor.map(load_single, files)
new_array = np.empty((0, 39), dtype=np.float32)
for partial_array in results:
new_array = np.vstack([new_array, partial_array])