python - Openpyxl 的 iter_rows 非常慢,即使 read_only=True?
问题描述
我尝试编写一个 Python-3 函数,将 xlsx 文件中的数字数据读取到 numpy 数组中。我通常只想从特定工作表中读取特定区域。这些区域可能很小(十几个单元格)或相当大(5000 x 10,000 很容易)。我对文本几乎不感兴趣,对功能、数字、格式一点也不感兴趣。到目前为止,这是我的方法(我编写的代码仅供我自己使用,因此我不遵循一些/许多约定和 PEP):
def xlsreadOnly(file, rangeName, sheet = 'Sheet1', dataOnly = True, forceNum = False):
from openpyxl import load_workbook
from openpyxl.utils.cell import coordinate_from_string, column_index_from_string
from numpy import empty, nan
import io
with open(file, 'rb') as f:
in_mem_file = io.BytesIO(f.read())
wb = load_workbook(filename = in_mem_file, read_only = True, data_only = dataOnly)
ws = wb[sheet]
# find the indeces of left-upper and right-lower cells
areal = rangeName
w = areal.find(":")
lu = coordinate_from_string(areal[0:w])
luR = lu[1]
luC = column_index_from_string(lu[0])
rl = coordinate_from_string(areal[w+1:])
rlR = rl[1]
rlC = column_index_from_string(rl[0])
# initialize variable raw
raw = empty([rlR-luR+1, rlC-luC+1], dtype = 'object')
ctor = 0
# iterate over the rows from left-upper to right-lower cell
for row in ws.iter_rows(min_row=luR, max_row=rlR, min_col=luC, max_col=rlC, values_only=True):
raw[ctor, :] = np.array(row)
ctor += 1
return raw
我使用 an in_mem_file
,因为它在早期版本中加快了该功能。工作簿加载为read_only
,感兴趣的区域可分段为左上排 ( luR
)、右下排 ( lrR
) 等。该变量raw
预先以适当的大小初始化,因此没有append
.
有趣的部分似乎是循环
for row in ws.iter_rows(min_row=luR, max_row=rlR, min_col=luC, max_col=rlC, values_only=True):
我读取的工作表大小为 2535 x 4763。如果我读取大小为 100 x 4763 的区域,则该函数需要大约 4.2 秒(i5-9600、3.7GHz、16GB RAM、SSD),这听起来对我来说太长了. 如果我将区域缩小到 100 x 3,仍然需要 4.0 秒(是的,对于 300 个单元格!)。看起来好像列数实际上是无关紧要的。但是,时间几乎与行数呈线性关系,因此将区域增加到 500 x 4763 大约需要 22 秒。读取整个文件需要相应的时间。
删除转换为 numpy 数组raw[ctor, :] = np.array(row)
几乎不会增加计算时间。
我真的认为我错过了一些非常明显的东西,但是在搜索了几天之后,我仍然没有看到它!预先真诚地感谢您指出我的错误。
编辑:@Charlie Clark,你的评论是 100% 正确的,代码不是很容易阅读,并且有一些不必要的代码。我做了一些改变,希望现在更好。我还在必要时更新了文本。我忘了提到从一个小工作表中读取相同的 100x3 区域只需几毫秒。所以问题似乎出在(我的理解)iter_rows()
for循环中。
解决方案
推荐阅读
- typo3 - 扩展在 ext_tables.php 中更改 TCA 检查 ExtensionManagementUtility 和 $GLOBALS["TCA"]
- nativescript - 无法加载操作栏图标:res://back
- angular - 如何在angular 4中使用带有wiris插件的ckeditor
- c# - Web 应用程序之间的通信
- python - numpy,合并两个不同形状的数组
- javascript - 在 Laravel 5.7 的 vue js 中使用 jquery
- awk - awk:在同一行打印带有不同数量的附加字段的 $1
- php - 如何从数组中删除具有重复 ID 和负数的键
- c# - 在 Visual Studio for Mac 中自动保存
- c++ - C ++创建2个类,其中第二个类继承第一个类,构造函数在创建对象的类中运行