Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 加快Excel数据到Pandas的速度_Python_Excel_Python 3.x_Pandas_Performance - Fatal编程技术网

Python 加快Excel数据到Pandas的速度

Python 加快Excel数据到Pandas的速度,python,excel,python-3.x,pandas,performance,Python,Excel,Python 3.x,Pandas,Performance,我有一个非常简单的代码,其中我有一组文件名,我需要打开每个文件名并提取一些数据以供以后操作 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=

我有一个非常简单的代码,其中我有一组文件名,我需要打开每个文件名并提取一些数据以供以后操作

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-2秒,并且numpy堆叠需要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.8秒。谢谢大家的帮助。

这里是一个快速基准测试(扩展)。显然,对于test.xlsx文件,直接使用xlrd要比pandas快一些。如果.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)    
两个小贴士:

  • ProcessPoolExecutor具有比纯多处理池更好的接口
  • 如果加载大文件,则必须控制如何使用内存
如果不提供类型,大多数库将使用可能的最大值(64位)。如果即使在控制了数据类型之后,数据也无法放入内存,则需要考虑分区和溢出到磁盘

下面是为控制数据类型和Executor接口而编写的代码示例

来自concurrent.futures导入ProcessPoolExecutor
从openpyxl导入加载工作簿
作为pd进口熊猫
将numpy作为np导入
def加载_单个(文件):
文件名=rootdir+“/”+str(文件)
wb\u loop=load\u工作簿(文件名,只读=True,数据=True)
ws_loop=wb_loop[“SHEET1”]
df=pd.DataFrame(ws_loop.values)
partial_array=df.loc[4:43,:13].values.astype(np.float32)
返回部分数组
def run():
executor=ProcessPoolExecutor(最大工人数=4)
files=唯一的文件名[1:]
结果=executor.map(加载单个文件)
new_array=np.empty((0,39),dtype=np.float32)
对于结果中的部分_数组:
新数组=np.vstack([新数组,部分数组])

将Excel文件读入Pandas自然比其他选项(CSV、Pickle、HDF5)慢。如果你想提高性能,我强烈建议你考虑这些其他格式。除非我在打开之前自己做了转换,否则你不可能尝试<代码> Read Excel()/<代码> <代码> SeeTyNe= =“SHIET1”< /代码>和<代码> dType =对象< /代码>?在读取数据时,这些通常是明显的优化。我尝试了一下,上次尝试时时间增加到了3秒左右。可能不得不再给它一次goI曾经尝试过使用它,但我没有运气,尽管如此,还是谢谢你的建议