Excel包可用于从R读取和写入xlsx
电子表格。不幸的是,即使对于中等大的电子表格,也可能发生java.lang.OutOfMemoryError
。特别地,
对象错误(“RJavaTools”,“Ljava/lang/
;”,"invokeMethod",cl,:
java.lang.OutOfMemoryError:.jcall("RJavaTools","Ljava/lang/Object;","newInstance",.jfindClass(类),:
java.lang.OutOfMemoryError:超出GC开销限制
(其他相关的异常也是可能的,但比较少见。)
在阅读电子表格时,也提出了类似的问题。
Importing a big xlsx file into R?
与CSV相比,使用Excel电子表格作为数据存储介质的主要优点是,您可以在同一文件中存储多个工作表,因此这里我们考虑要写入的数据框列表,每个工作表一个数据框。此示例数据集包含40个数据框,每个框有两列,最多200k行。它被设计得足够大,但您可以通过更改n_sheets
和n_rows
来更改大小。
library(xlsx)
set.seed(19790801)
n_sheets <- 40
the_data <- replicate(
n_sheets,
{
n_rows <- sample(2e5, 1)
data.frame(
x = runif(n_rows),
y = sample(letters, n_rows, replace = TRUE)
)
},
simplify = FALSE
)
names(the_data) <- paste("Sheet", seq_len(n_sheets))
将其写入文件的自然方法是使用createWorkbook
创建一个工作簿,然后循环调用createSheet
和addDataFrame
的每个数据框。最后,可以使用saveWorkbook
将工作簿写入文件。我已经向循环中添加了消息,以便更容易地看到它在哪里失败。
wb <- createWorkbook()
for(i in seq_along(the_data))
{
message("Creating sheet", i)
sheet <- createSheet(wb, sheetName = names(the_data)[i])
message("Adding data frame", i)
addDataFrame(the_data[[i]], sheet)
}
saveWorkbook(wb, "test.xlsx")
在具有8 8GB内存的机器上以64位运行此程序,它会在第一次运行addDataFrame
时抛出GC overhead limit exceeded
错误。
如何使用xlsx
将大型数据集写入Excel电子表格
发布于 2014-02-21 22:53:26
这是一个已知的问题:http://code.google.com/p/rexcel/issues/detail?id=33
虽然未解决,但问题页面links to a solution by Gabor Grothendieck建议在加载rJava
包之前通过设置java.parameters
选项来增加堆大小。(rJava
是xlsx
的依赖项。)
options(java.parameters = "-Xmx1000m")
值1000
是允许Java heap使用的内存的兆字节数;它可以替换为您喜欢的任何值。我的实验表明,值越大越好,并且您可以愉快地使用您的全部RAM权限。例如,我使用以下命令获得最好的结果:
options(java.parameters = "-Xmx8000m")
在具有8 8GB的机器上。
可以通过在循环的每次迭代中请求垃圾收集来获得进一步的改进。正如@gjabel所指出的,可以使用gc()
执行R垃圾收集。我们可以定义一个调用Java System.gc()
方法的Java垃圾收集函数:
jgc <- function()
{
.jcall("java/lang/System", method = "gc")
}
然后,可以将循环更新为:
for(i in seq_along(the_data))
{
gc()
jgc()
message("Creating sheet", i)
sheet <- createSheet(wb, sheetName = names(the_data)[i])
message("Adding data frame", i)
addDataFrame(the_data[[i]], sheet)
}
通过这两个代码修复,代码在抛出错误之前一直运行到i = 29
。
我尝试过的一种技术是在每次迭代时使用write.xlsx2
将内容写入文件,但没有成功。这比其他代码慢,并且在第10次迭代时就崩溃了(但至少有部分内容被写入文件)。
for(i in seq_along(the_data))
{
message("Writing sheet", i)
write.xlsx2(
the_data[[i]],
"test.xlsx",
sheetName = names(the_data)[i],
append = i > 1
)
}
发布于 2016-01-14 19:39:06
基于@richie-cotton的回答,我发现在jgc
函数中添加gc()
可以保持较低的CPU使用率。
jgc <- function()
{
gc()
.jcall("java/lang/System", method = "gc")
}
我之前的for
循环仍然在处理原始的jgc
函数,但是有了额外的命令,我不再遇到GC overhead limit exceeded
错误消息。
发布于 2017-10-11 19:23:35
上述错误的解决方案:请使用下面提到的r- code:
detach(package:xlsx)
detach(package:XLConnect)
library(openxlsx)
并且,尝试再次导入该文件,您将不会得到任何错误,因为它为我工作。
https://stackoverflow.com/questions/21937640
复制相似问题