错误“无法分配...”可能来自 rm() 不会立即释放内存。因此,当您加载第二个对象时,第一个对象仍然占用 RAM。未分配给任何名称(变量)的对象将在 R 自行决定的时间点由 R 收集垃圾。
大多数补救措施来自不将整个对象加载到 RAM 中:
-
如果您正在使用矩阵,请使用 bigmemory 包创建 filebacked.big.matrix()。使用var[...,...] 语法将您的数据写入此对象,就像普通矩阵一样。然后,在一个新的 R 会话(以及一个新的 R 脚本以保持可重复性)中,您可以从磁盘加载此矩阵并对其进行修改。
-
mmap 包使用类似的方法,利用操作系统将 RAM 页面映射到磁盘的能力。所以它们在程序中看起来就像在 ram 中一样,但是是从磁盘读取的。为了提高速度,操作系统负责将相关部分保存在 RAM 中。
-
如果您使用数据框,您可以使用 fst 和 feather 之类的包,它们使您能够仅将部分数据框加载到变量中。
-
将您的数据框传输到 sqlite 之类的数据库中,然后使用 R 访问该数据库。dbplyr 包使您可以将数据库视为 tidyverse 样式的数据集。这是RStudio help page。你也可以使用raw SQL commands with the package DBI
另一种方法是不以交互方式编写,而是编写一个只处理一个对象的 R 脚本:
编写一个名为 processBigObject.R 的 R 脚本,使用 commandArgs() 从命令行获取大对象的文件名:
#!/usr/bin/env Rscript
#
# Process a big object
#
# Usage: Rscript processBigObject.R <FILENAME>
input_filename <- commandArgs(trailing = TRUE)[1]
output_filename <- commandArgs(trailing = TRUE)[2]
# I'm making up function names here, do what you must for your object
o <- readBigObject(input_filename)
s <- calculateSmallerSummaryOf(o)
writeOutput(s, output_filename)
然后,编写一个shell脚本或使用system2()多次调用该脚本,使用不同的文件名。因为 R 在每个对象之后终止,所以内存被释放:
system2("Rscript", c("processBigObject.R", "bigObject1.dat", "bigObject1_result.dat"))
system2("Rscript", c("processBigObject.R", "bigObject2.dat", "bigObject2_result.dat"))
system2("Rscript", c("processBigObject.R", "bigObject3.dat", "bigObject3_result.dat"))
...