2

我经常从产生非标准 Excel 格式的源接收数据,该格式无法被readxl::read_excel. 这是github问题线程。因此,我有一个完整的目录树,其中包含数百个(几乎)Excel 文件,我想将这些文件读入 R 并与plyr::ldply这些文件结合起来。但是,可以通过XLConnect::loadWorkbook. 但不幸的是,即使为 Java 虚拟机分配了大量内存,它也总是在读取几个文件后崩溃。我尝试将这三行添加到我的导入函数中:

options(java.parameters = "-Xmx16g")
detach("package:XLConnect", unload = TRUE)
library(XLConnect)
xlcFreeMemory()

但是,我仍然得到:

错误:OutOfMemoryError (Java):Java 堆空间

我需要做的就是将它们重新保存在 Excel 中,然后它们从readxl::read_excel. 我希望我也可以批量重新保存它们,XLConnect然后在 using 中读取它们readxl::read_excel。不幸的是,使用 Linux,我不能只编写 Excel 脚本来重新保存它们。有没有人有另一种解决方法?

4

1 回答 1

1

由于您使用的是 Linux,因此运行 Excel 宏来重新保存电子表格看起来很困难。

您可以使用 XLConnect 启动一个单独的 R 进程来读取每个电子表格。这至少可以通过两种方式完成:

  • 使用脚本文件运行 Rscript,将电子表格的名称传递给它。将数据保存到 .RData 文件中,然后在您的主 R 进程中读回它。

  • 从并行包中使用parLapply,将电子表格名称的向量和读取文件的函数传递给它。在这种情况下,您不必将数据保存到磁盘作为中间步骤。但是,您可能必须分块执行此操作,因为从属进程将慢慢耗尽内存,除非您重新启动它们。

后者的例子:

files <- list.files(pattern="xlsx$")
filesPerChunk <- 5
clustSize <- 4  # or how ever many slave nodes you want
runSize <- clustSize * filesPerChunk

runs <- length(files)%/%runSize + (length(files)%%runSize != 0)

library(parallel)

sheets <- lapply(seq(runs), function(i) {
    runStart <- (i - 1) * runSize + 1
    runEnd <- min(length(files), runStart + runSize - 1)
    runFiles <- files[runStart:runEnd]

    # periodically restart and stop the cluster to deal with memory leaks
    cl <- makeCluster(clustSize)
    on.exit(stopCluster(cl))

    parLapply(cl, runFiles, function(f) {
        require(XLConnect)
        loadWorkbook(f, ...)
    })
})

sheets <- unlist(sheets, recursive=FALSE)  # convert list of lists to a simple list
于 2015-07-27T13:43:19.730 回答