为什么我的代码在openpyxl的只读模式下gitting速度较慢?

2024-10-03 06:23:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个类函数“loadxl()”,它使用openpyxl将数据从Excel读取到Python。我曾试图通过使用“只读”模式和内置迭代器使其速度更快,但我尝试优化函数的速度却只有原始代码的一半

我正在读取的数据是在9241 X 14矩阵中构造的。我正在使用这些数据初始化类“Case”中的变量,这些变量大部分是“numpy”数组

在我的初始代码中,我没有使用“只读”工作簿,而是使用“sheet.cell()”方法访问单元格。这是我的原始代码:

import numpy as np
import openpyxl as opyxl

class Case:
    def __init__(
    self, filepath = None
    ):

       #Bus data
       self.sbase = 500 #Default MVA value
       self.numbus = np.empty(0, dtype = np.int32)
       self.slackbusnr = []
       self.busname = np.empty(0, dtype = np.str)
       self.buscod = np.empty(0, dtype = np.int32)
       self.basekv = np.empty(0, dtype = np.double)
       self.gs = np.empty(0, dtype = np.double)
       self.bs = np.empty(0, dtype = np.double)
       self.area = np.empty(0, dtype = np.int32)
       self.zone = np.empty(0, dtype = np.int32)
       self.nbuses = 0
       self.vomag = np.empty(0, dtype = np.double)
       self.voang = np.empty(0, dtype = np.double)

    def loadxl(self,filename):       
       wb = opyxl.load_workbook(filename)
       bus = wb.get_sheet_by_name('Bus-data')
       i = 1
       while (bus.cell(row = i,column = 1).value is not None):

            self.numbus = np.append(self.numbus,int(bus.cell(row = i, column = 1).value))
            if(int(bus.cell(row = i, column = 3).value) == 3):
                self.slackbusnr = self.nbuses
            self.buscod = np.append(self.buscod, int(bus.cell(row = i, column = 4).value))
            self.pload = np.append(self.pload, float(bus.cell(row = i, column = 5 ).value)/self.sbase)
            self.qload = np.append( self.qload, float(bus.cell(row = i, column = 6).value)/self.sbase)
            self.gs = np.append(self.gs, float(bus.cell(row = i, column = 7).value)/self.sbase)
            self.bs = np.append(self.bs, float(bus.cell(row = i, column = 8).value)/self.sbase)
            self.area = np.append(self.area,int(bus.cell(row = i, column = 9).value))
            self.vomag = np.append(self.vomag, float(bus.cell(row = i, column = 10).value))
            self.voang = np.append(self.voang, float(bus.cell(row = i, column = 11).value)/180*math.pi)
            self.basekv  = np.append(self.basekv,float(bus.cell(row = i, column = 12).value))        
            self.zone = np.append(self.zone,int(bus.cell(row = i, column = 13).value))
            self.nbuses += 1
            i+=1

原始代码使用大约10秒来读取数据。在阅读了openpyxl的文档和一大堆在线文章之后,我意识到我可以通过加载一个“只读”工作簿来优化代码。但是,.cell()方法在只读模式下速度非常慢,因此我使用了“ws.iter_rows()”而不是while循环。新守则如下:

def loadxl2(filename): 

   wb = opyxl.load_workbook(filename, read_only = True)
                    bus = wb.get_sheet_by_name('Bus-data')
   for row in bus.iter_rows(min_col = 1, min_row = 1, values_only = True):
                if(row[0] == None):
                    break
                self.numbus = np.append(self.numbus,int(row[0]))
                self.busname = np.append(self.busname, str(row[1]))
                self.buscod = np.append(self.buscod, int(row[2]))
                if(int(row[2]) == 3):
                    self.slackbusnr = self.nbuses
                self.pload = np.append(self.pload, float(row[ 3])/self.sbase)
                self.qload = np.append( self.qload, float(row[4])/self.sbase)
                self.gs = np.append(self.gs, float(row[5])/self.sbase)
                self.bs = np.append(self.bs, float(row[6])/self.sbase)
                self.area = np.append(self.area,float(row[7]))
                self.vomag = np.append(self.vomag, float(row[8]))
                self.voang = np.append(self.voang, float(row[9])/180*math.pi)
                self.basekv  = np.append(self.basekv,float(row[10]))        
                self.zone = np.append(self.zone,float(row[11]))
                self.nbuses += 1

问题是:新代码的速度大约是原代码的一半

我在这两个代码中使用了“line_profile”,发现即使使用“wb.load_工作簿(read_only=True)”加载工作簿也要快得多,新代码中的for循环比while循环慢60倍。(在两个循环中添加数据显示了相同的性能)

openpyxl文档和在线博客/帖子都说,在只读模式下,通过使用内置迭代器读取数据应该更快,那么有人知道我的代码可能有什么问题吗


Tags: 代码selfvaluenpcellcolumnfloatempty
2条回答

当你说慢的时候?你说的慢是什么意思?几秒钟、几分钟或几小时

这是Excel的一个小文件,因此时间可能主要取决于加载库。也就是说,每次对相同的列执行相同的操作。让numpy同时对数组中的元素执行所有操作可能是有意义的。毕竟,这是向量运算的要点

我注意到您使用了self.numbus,这意味着您使用的是类,我们看不到您的全部代码

降低pyautogui速度的一个可靠方法是多次打开工作簿。因此,您可能需要检查工作簿是否只打开一次

另一件事是我看不到什么是np。你能添加更多的代码吗

既然你在上课,我想知道你是否把所有的东西都装进了内存。这也可能会让它慢一点

我有一个类似的项目,我一列一列地写,这也不是一个好主意。它变得很慢。然后我打开了另一个工作簿来写入数据。基本上是在内存中创建工作簿的副本。然后我写了一次到文件里。 因此,基本上:查看文件写入操作的数量,并减少它

相关问题 更多 >