读取大型Excel xlsx文件的最快方法?是否并行化?

Pyt*_*ous 5 parallel-processing r readxl

我的问题是:

  • 将大型(ish).xlsx Excel文件读入R的最快方法是什么?10到200 MB的xlsx文件,多张纸。

  • 可以使用某种并行处理吗,例如,每个核心读取多页Excel文件的一张纸?

  • 还有其他可以执行的优化吗?

到目前为止,我所了解的(以及我尚未了解的):

  • 如果要从旋转磁盘读取数据,正如我所愿,并行处理实际上可能会减慢读取速度,因为多个进程试图从同一个文件读取数据。但是,并行处理可能有助于转换和推断数据类型?不知道readxl从磁盘读取(我认为是IO绑定)还是转换数据类型(我估计是CPU绑定)花了多少钱。
  • 对于SSD驱动器,可能有所不同。如果有很大的改进,我可能会将数据复制到SSD驱动器并从那里读取。
  • data.table :: fread可以加快文本文件的读取速度(尽管我不完全理解为什么),但是它不能用于excel文件-可以吗?
  • 我从这个答案中了解到readxl往往比openxlsx

我只对表格数据感兴趣;我对Excel格式,图表,文本标签或任何其他类型的数据都不感兴趣。

我可能希望导入整洁的小标题,但不一定。然后,我需要将表导出到Microsoft SQL Server中。

背景知识:我主要使用Python,并且对R完全陌生。使用Python 读取大型Excel文件非常缓慢。我已经看到R的readxl速度比Python快pandas(在15页xlsx上,每页有10,000行和32列:readxl 5.6秒,熊猫33秒),这太棒了!但是,我仍然想了解是否有任何方法可以使导入速度更快。我可以使用R读取文件,将其导出到SQL,然后使用从SQL中读取的Python继续其余的工作流程。

我认为转换为CSV并不是最好的选择,尤其是当readxl远比Python快得多时;基本上转换为csv所需的时间可能比我从csv读取而不是excel节省​​的时间要长。另外,至少对于Python(我不太了解R是否足以使用readxl对其进行全面测试)而言,使用xlsx推断数据类型要比使用csv更好。

我的代码(欢迎提出任何批评或建议):

library(readxl)
library(tidyverse)
library(tictoc)


this.dir <- dirname(parent.frame(2)$ofile)
setwd(this.dir)

tic("readxl")

path <- "myfile.xlsx"
sheetnames <- excel_sheets(path)
mylist <- lapply(excel_sheets(path), read_excel, path = path)

names(mylist) <- sheetnames
toc()
Run Code Online (Sandbox Code Playgroud)

cle*_*ens 6

您可以尝试使用该parallel程序包并行运行它,但是很难估计没有示例数据时的运行速度:

library(parallel)
library(readxl)

excel_path <- ""
sheets <- excel_sheets(excel_path)
Run Code Online (Sandbox Code Playgroud)

使集群具有指定数量的核心:

cl <- makeCluster(detectCores() - 1)
Run Code Online (Sandbox Code Playgroud)

用于parLapplyLB浏览Excel工作表并使用负载平衡并行阅读它们:

parLapplyLB(cl, sheets, function(sheet, excel_path) {
  readxl::read_excel(excel_path, sheet = sheet)
}, excel_path)
Run Code Online (Sandbox Code Playgroud)

您可以使用该软件包microbenchmark来测试某些选项的运行速度:

library(microbenchmark)

microbenchmark(
  lapply = {lapply(sheets, function(sheet) {
    read_excel(excel_path, sheet = sheet)
  })},
  parralel = {parLapplyLB(cl, sheets, function(sheet, excel_path) {
    readxl::read_excel(excel_path, sheet = sheet)
  }, excel_path)},
  times = 10
)
Run Code Online (Sandbox Code Playgroud)

就我而言,并行版本更快:

Unit: milliseconds
     expr       min        lq     mean    median        uq      max neval
   lapply 133.44857 167.61801 179.0888 179.84616 194.35048 226.6890    10
 parralel  58.94018  64.96452 118.5969  71.42688  80.48588 316.9914    10
Run Code Online (Sandbox Code Playgroud)

测试文件包含6张纸,每张纸包含此表:

    test test1 test3 test4 test5
 1     1     1     1     1     1
 2     2     2     2     2     2
 3     3     3     3     3     3
 4     4     4     4     4     4
 5     5     5     5     5     5
 6     6     6     6     6     6
 7     7     7     7     7     7
 8     8     8     8     8     8
 9     9     9     9     9     9
10    10    10    10    10    10
11    11    11    11    11    11
12    12    12    12    12    12
13    13    13    13    13    13
14    14    14    14    14    14
15    15    15    15    15    15
Run Code Online (Sandbox Code Playgroud)

注意:stopCluster(cl)该过程完成后,您可以用来关闭工作程序。