从R写入Excel时处理java.lang.OutOfMemoryError
从R写入Excel时处理java.lang.OutOfMemoryError,r,xlsx,R,Xlsx,xlsx包可用于从R读取和写入Excel电子表格。不幸的是,即使是中等规模的电子表格,java.lang.OutOfMemoryError。特别是, .jcall(“RJavaTools”、“Ljava/lang/Object;”、“invokeMethod”、cl、: java.lang.OutOfMemoryError:java堆空间 .jcall(“RJavaTools”、“Ljava/lang/Object;”、“newInstance”、.jfindClass(类)中出现错误: jav
xlsx
包可用于从R读取和写入Excel电子表格。不幸的是,即使是中等规模的电子表格,java.lang.OutOfMemoryError
。特别是,
.jcall(“RJavaTools”、“Ljava/lang/Object;”、“invokeMethod”、cl、:java.lang.OutOfMemoryError:java堆空间 .jcall(“RJavaTools”、“Ljava/lang/Object;”、“newInstance”、.jfindClass(类)中出现错误:
java.lang.OutOfMemoryError:超出GC开销限制 (其他相关例外情况也是可能的,但更为罕见。) 在阅读电子表格时,针对此错误也提出了类似的问题
使用Excel电子表格作为CSV上的数据存储介质的主要优点是可以在同一文件中存储多个表,因此,我们考虑要在每个工作表中写入一个数据帧的数据帧的列表。该示例数据集包含40个数据帧,每个数据帧具有最多200K行的两列。o可能有问题,但您可以通过更改
n\u表
和n\u行
来更改大小
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))
在具有8GB RAM的机器上以64位运行此命令时,它会在第一次运行addDataFrame
时抛出GC开销限制超出
错误
如何使用xlsx
将大型数据集写入Excel电子表格?这是一个已知的问题:
在未解决问题的情况下,在加载rJava
包之前,通过设置java.parameters
选项来增加堆大小的问题页面。(rJava
是xlsx
的依赖项)
值1000
是允许Java堆的RAM的兆字节数;它可以替换为您喜欢的任何值。我的实验表明,值越大越好,您可以愉快地使用您的全部RAM权限。例如,我使用以下方法获得了最佳结果:
options(java.parameters = "-Xmx8000m")
在具有8GB RAM的机器上
通过在循环的每次迭代中请求垃圾收集,可以获得进一步的改进。如@gjabel所述,R垃圾收集可以使用执行。我们可以定义一个调用Java方法的Java垃圾收集函数:
基于@richie cotton answer,我发现在
jgc
函数中添加gc()
可以保持较低的CPU使用率
jgc <- function()
{
gc()
.jcall("java/lang/System", method = "gc")
}
jgc如果要逐行写入,也可以在循环中使用gc()。gc()代表垃圾回收。gc()可用于任何内存问题。上述错误的解决方案:
请使用以下提到的r代码:
detach(package:xlsx)
detach(package:XLConnect)
library(openxlsx)
并且,再次尝试导入该文件,您不会得到任何错误,因为它对我有效。我在write.xlsx()方面遇到问题但后来意识到我无意中运行了32位R。将其换成64位已经解决了这个问题。现在可以通过将xlsx
包换成openxlsx
包来避免整个问题,该包依赖于Rcpp
,而不是Java。readxl
是另一个选择r新的C/C++替代方案,看起来很有希望。不幸的是,我发现这两种方案在检测和读取日期方面都是垃圾——都以无法修复的混乱状态结束,即Excel日期格式:\@RichieCotton,不错的替代方案。但是,openxlsx无法读取.xls或.xlm文件!(2007 Excel文件格式)。调用选项(java.parameters=“-Xmx8000m”)
加载前rJava
,xlsxjars
,xlsx
解决了.jcall中的错误(“RJavaTools”,“Ljava/lang/Object;”,“invokeMethod“,cl,:org.apache.poi.POIXMLException:java.lang.reflect.InvocationTargetException调用:getNetwork…->.jrcall->.jcheck->.RHEL 6.3 x86_64,java 1.7.0_79(Oracle)中的调用执行已暂停,rJava_0.9-7,xlsxjars_0.6.0,xlsx_0.5.7两条评论:xlConnect也有同样的问题。更重要的是,告诉别人使用不同的库并不能解决被引用库的问题。这里的目标是留在xlsx包中。还有其他线程专门用于xlConnect。
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)
}
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
)
}
jgc <- function()
{
gc()
.jcall("java/lang/System", method = "gc")
}
detach(package:xlsx)
detach(package:XLConnect)
library(openxlsx)