我正在尝试在12核计算机上使用多处理程序来读取Excel文件–一个60MB的文件,每页15张,每行10,000行.使用pandas.read_csv导入所有工作表并且不进行并行化仍然需要大约33秒.
如果我使用pool.map(),它可以工作,但是比非并行版本要花更长的时间:150秒vs 33!
如果我使用pool.map_async()需要36秒,但是我似乎无法访问(因此无法检查)输出!
我的问题是:
>我做错了什么? pool.map和pool.map_async都大致需要
即使我在read_single_sheet中将nrows = 10设置为同一时间
功能;同时读取10行还是10,000 –这是怎么回事
可能?
>如何获得pool.map_async()的结果?我努力了
输出= [数据帧中p的p.get()],但不起作用:
MapResult
object is not iterable
>这更多是受IO约束而不是cpu约束
问题?不过,为什么pool.map需要这么长时间?
从CSV读取相同的数据(每个Excel工作表已保存到单独的CSV)在我的计算机上需要2秒钟.但是,对于我需要做的事情,CSV并不是一个很好的选择.我通常有10到20个中型标签;与等待熊猫阅读它们相比,手动转换它们通常会花费更长的时间,此外,如果我收到更新的版本,则必须再次进行手动转换.
我知道我可以在Excel中使用VBA脚本自动将每张工作表保存为CSV,但是从Excel读取数据时,大多数情况下可以正确推断数据类型-CSV并非如此,尤其是对于日期(我的日期从不为ISO yyyy-mm-dd ):我必须确定日期字段,指定格式等-仅从Excel读取通常会更快.尤其是因为这些任务往往是一次性的:我将数据导入一次,如果收到更新,则可能导入两次或3次,将其存储在sql中,然后从sql中读取所有Python脚本.
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,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)
我的解决方案是:在R中执行!
我发布了here,它也显示了我的代码(非常少);基本上,在同一文件上,R的readxl用了5.6秒.回顾一下:
> xlsx中的Python:33秒
> CSV中的Python: 2秒
> xlsx中的R:5.6秒
该链接还有一个答案,表明并行化可以进一步加快处理速度.
我相信关键的区别在于pandas.read_csv依赖于C代码,而pandas.read_excel则依赖于更多的Python代码. R的readxl可能基于C.可以使用C分析器将xlsx文件导入Python,但是AFAIK到目前为止,尚无此类分析器.
这是一个可行的解决方案,因为在导入R后,您可以轻松地导出为保留有关数据类型的所有信息以及Python可以从中读取的格式(sql,parquet等).并非每个人都可以使用sql Server,但是镶木地板或sqlite之类的格式不需要任何其他软件.
因此,对工作流的更改很小:最初的数据加载(至少在我看来是一次性的)在R中,而其他所有内容继续在Python中.
我还注意到,使用R和DBI :: dbWriteTable将相同的工作表导出到sql比使用熊猫快得多(4.25秒对18.4秒).