Python 如何通过多处理将多张Excel表格导入pandas?
我试图在12核机器上使用多处理来读取Excel文件——一个60MB的文件,每个文件有15张纸和10000行。导入带有pandas.read_csv的所有工作表,并且没有并行化仍然需要大约33秒 如果我使用pool.map(),它可以工作,但比非并行版本需要更长的时间:150秒比33秒 如果我使用pool.map\u async()需要36秒,但我似乎无法访问(因此无法检查)输出 我的问题是:Python 如何通过多处理将多张Excel表格导入pandas?,python,pandas,python-multiprocessing,Python,Pandas,Python Multiprocessing,我试图在12核机器上使用多处理来读取Excel文件——一个60MB的文件,每个文件有15张纸和10000行。导入带有pandas.read_csv的所有工作表,并且没有并行化仍然需要大约33秒 如果我使用pool.map(),它可以工作,但比非并行版本需要更长的时间:150秒比33秒 如果我使用pool.map\u async()需要36秒,但我似乎无法访问(因此无法检查)输出 我的问题是: 我做错了什么?pool.map和pool.map_异步都需要大约 即使我在read_single_工作
- 我做错了什么?pool.map和pool.map_异步都需要大约 即使我在read_single_工作表中设置nrows=10,也会在同一时间进行 功能;同时,无论它读取10行还是10000行,这是怎么回事 可能吗
- 如何获得pool.map_async()的结果?我试过了
但它不起作用:output=[p.get()表示数据帧中的p]
- 这是IO绑定还是CPU绑定 问题不过,pool.map为什么要花这么长时间
import numpy as np
import pandas as pd
import time
import multiprocessing
from multiprocessing import Pool
def parallel_read():
pool = Pool(num_cores)
# reads 1 row only, to retrieve column names and sheet names
mydic = pd.read_excel('excel_write_example.xlsx', nrows=1, sheet_name=None)
sheets =[]
for d in mydic:
sheets.extend([d])
dataframes = pool.map( read_single_sheet , sheets )
return dataframes
def parallel_read_async():
pool = Pool(num_cores)
# reads 1 row only, to retrieve column names and sheet names
mydic = pd.read_excel('excel_write_example.xlsx', nrows=1, sheet_name=None)
sheets =[]
for d in mydic:
sheets.extend([d])
dataframes = pool.map_async( read_single_sheet , sheets )
output = None
# this below doesn`t work - can`t understand why
output = [p.get() for p in dataframes]
return output
def read_single_sheet(sheet):
out = pd.read_excel('excel_write_example.xlsx', sheet_name=sheet )
return out
num_cores = multiprocessing.cpu_count()
if __name__=='__main__':
start=time.time()
out_p = parallel_read()
time_par = time.time() -start
out_as = parallel_read_async()
time_as = time.time() - start - time_par
我用来创建Excel的代码是:
import numpy as np
import pandas as pd
sheets = 15
rows= int(10e3)
writer = pd.ExcelWriter('excel_write_example.xlsx')
def create_data(sheets, rows):
df = {} # dictionary of dataframes
for i in range(sheets):
df[i] = pd.DataFrame(data= np.random.rand(rows,30) )
df[i]['a'] = 'some long random text'
df[i]['b'] = 'some more random text'
df[i]['c'] = 'yet more text'
return df
def data_to_excel(df, writer):
for d in df:
df[d].to_excel(writer, sheet_name = str(d), index=False)
writer.close()
df = create_data(sheets, rows)
data_to_excel(df, writer)
下面简要介绍了如何绕过文件锁并在对代码进行少量更改的情况下实现并发:
导入io
导入xlrd
从functools导入部分
def read_表(浅黄色,表名):
#仅读取1行,以检索列名和图纸名
df=pd.read\u excel(buff,sheetname=sheetname)
返回df
如果“名称”=“\uuuuuuuu主要”:
开始=时间。时间()
time\u par=time.time()-开始
xl=xlrd.open_工作簿(“myfile.xls”)#您填写此
sheets=xl.book.sheet_name()
buff=io.BytesIO()
xl.转储(buff)
buff.seek(0)
目标=部分(读表,浅黄色)
将池(num_进程)作为p:
dfs=p.map(目标,图纸名称)
time\u as=time.time()-start-time\u par
这里发生了几件事:
- 调用
实际上占用了pd.read\u excel('excel\u write\u example.xlsx',nrows=1,sheet\u name=None)
似乎要花费的36秒parallel\u read\u async
立即返回,为您提供map\u async
对象,您通过尝试对其进行迭代立即导致异常,因此在此版本中,MapResult
函数基本上没有做任何工作read\u single\u sheet
- 此外,
withpd.read\u excel
所用的时间与sheet\u name=None
等所用的时间一样长。因此,在您的sheet\u name='1'
函数中,每个进程都在解析每张工作表的每一行。这就是为什么要花这么长时间parallel\u read
如果您可以选择生成(或接收?)xls文件,那么使用这些文件应该会更快。除此之外,如果非并行处理的速度不可接受,那么导出到csv选项可能是您的最佳选择。我将此作为一个答案发布,因为虽然它没有回答如何在Python中实现这一点的问题,但它仍然提供了一个切实可行的替代方案,可以大大加快读取时间,因此,任何Python用户都可能对它感兴趣;此外,它只依赖于开源软件,并且只需要用户学习R中的几个命令 我的解决方案是:在R中完成 我发布了关于它的信息,这也显示了我的(非常小的)代码;基本上,在同一个文件上,R的readxl花费了5.6秒。重述:
- 来自xlsx的Python:33秒
- 来自CSV的Python:约2秒
- 来自xlsx的R:5.6秒
pandas.read\u cs
v依赖于C代码,而pandas.read\u excel
依赖于更多的Python代码。R的readxl
可能基于C。可以使用C解析器将xlsx文件导入到Python中,但目前还没有这样的解析器
这是一个可行的解决方案,因为在导入到R中之后,您可以轻松地导出为一种格式,该格式保留了关于数据类型的所有信息,并且Python可以从中读取(SQL、parquet等)。并非每个人都有可用的SQL server,但是像parquet或sqlite这样的格式不需要任何额外的软件
因此对工作流的更改是最小的:初始数据加载(至少在我的例子中是一次性的)在R中,其他所有内容都继续在Python中。
我还注意到,使用R和DBI::dbWriteTable
将相同的工作表导出到SQL要比使用pandas
快得多(4.2)