我经常从产生非标准Excel格式的来源接收数据,readxl::read_excel
无法读取该格式。这是github issue thread。因此,我有一个完整的目录树,其中包含数百个(几乎)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
批量重新保存它们,然后使用readxl::read_excel
读取它们。不幸的是,使用Linux,我只能编写Excel脚本来重新保存它们。有没有人有另一种解决方法?
答案 0 :(得分:1)
由于您使用的是Linux,因此运行Excel宏来重新保存电子表格看起来很困难。
您可以启动一个单独的R进程来使用XLConnect读取每个电子表格。这可以通过至少两种方式完成:
使用脚本文件运行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