python - 如何使用多处理将多个 Excel 工作表导入 Pandas ?

标签 python pandas python-multiprocessing

我正在尝试在 12 核机器上使用多处理来读取一个 Excel 文件——一个 60MB 的文件,每页有 15 张 10,000 行。使用 pandas.read_csv 导入所有工作表并且没有并行化仍然需要大约 33 秒。

如果我使用 pool.map() 它可以工作,但它比非并行版本需要更长的时间:150 秒对 33 秒!

如果我使用 pool.map_async() 需要 36 秒,但我似乎无法访问(因此无法检查)输出!

我的问题是:

  • 我做错了什么? pool.map 和 pool.map_async 都需要大致 同时,即使我在 read_single_sheet 中设置 nrows=10 功能;同时读取 10 行或 10,000 行 - 怎么样 可能吗?
  • 如何获得 pool.map_async() 的结果?我努力了 output = [p.get() for p in dataframes] 但它不起作用:

MapResult object is not iterable

  • 这是 IO 限制多于 CPU 限制吗 问题?不过,为什么 pool.map 需要这么长时间?

从 CSV 读取相同的数据(每个 Excel 工作表保存到一个单独的 CSV)在我的机器上需要 2 秒。但是,对于我需要做的事情,CSV 并不是一个好的选择。我经常有 10 到 20 个中型标签;手动转换它们通常比等待 pandas 读取它们花费的时间更长,而且如果我收到更新版本,我必须再次进行手动转换。

我知道我可以在 Excel 中使用 VBA 脚本自动将每张工作表保存为 CSV,但是从 Excel 读取数据类型时通常可以正确推断出数据类型——对于 CSV 则不然,尤其是对于日期(我的日期从来不是 ISO yyyy- mm-dd):我必须识别日期字段、指定格式等——仅从 Excel 读取通常会更快。特别是因为这些任务往往是一次性的:我导入数据一次,如果我收到更新可能会导入 2 次或 3 次,将其存储在 SQL 中,然后我的所有 Python 脚本都从 SQL 中读取。

我用来读取文件的代码是:

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)

最佳答案

我将此作为答案发布是因为,虽然它没有回答如何在 Python 中执行此操作的问题,但它仍然提供了一种可行的替代方法来实质性地加快阅读时间,因此它可以任何 Python 用户都感兴趣;此外,它仅依赖于开源软件,并且只需要用户学习 R 中的几个命令。

我的解决方案是:在 R 中完成!

我发布了它 here ,这也显示了我的(非常少的)代码;基本上,在同一个文件中,R 的 readxl耗时 5.6 秒。回顾一下:

  • 来自 xlsx 的 Python:33 秒
  • 来自 CSV 的 Python:大约2秒
  • 来自 xlsx 的 R:5.6 秒

该链接还有一个答案,表明并行化可以进一步加快进程。

我认为关键区别在于 pandas.read_cs v 依赖于 C 代码,而 pandas.read_excel依赖于更多的 Python 代码。 R 的 readxl可能基于 C。可能可以使用 C 解析器将 xlsx 文件导入 Python,但据我所知,目前还没有这样的解析器可用。

这是一个可行的解决方案,因为在导入到 R 之后,您可以轻松导出为保留所有数据类型信息的格式,Python 可以从中读取(SQL、parquet 等)。不是每个人都有可用的 SQL 服务器,但像 parquet 或 sqlite 这样的格式不需要任何额外的软件。

因此,对工作流程的更改是最小的:初始数据加载,至少在我的情况下,往往是一次性的,在 R 中,其他所有内容继续在 Python 中。

我还注意到使用 R 和 DBI::dbWriteTable 将相同的工作表导出到 SQL 的速度要快得多比pandas (4.25 秒对 18.4 秒)。

关于python - 如何使用多处理将多个 Excel 工作表导入 Pandas ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55505311/

相关文章:

python - 使用 pyodbc cursor.executemany() 时如何获得正确的行数

python - 使用 Panda/Numpy 搜索匹配字符串

python - 如何一次有效地运行多个 Pytorch 进程/模型?回溯 : The paging file is too small for this operation to complete

python - Matplotlib:多线图

python - 在 Google Colab 中使用 plotly 绘制超过 600 万行的数据集

python - Python Pandas 中的引擎 read_csv

python-3.x - 将包含字符串和缺失的列转换为DateTime

python - 在 python 中运行的多进程命令的最佳资源分配

python - 如何使用具有多个参数的函数运行多处理 python 请求

python - 无法在运行 CentOS v6 的 Cloudera 快速启动 VM v5.13 中安装 pyhive