公式 return 的 R 函数具有较大的内存印记

R function with formula return has large memory imprint

我有一个适合模型的函数,我用同一个大矩阵调用了很多次(每次都在内部创建不同的公式)。但是,R 似乎保存了我一路上使用的数据的副本,所以我的内存爆炸了。

函数内部的一个简单删除就避免了这个问题。 但是,有没有一种通用的方法可以避免每次都保留整个环境?

例如运行以下,

test <- function(X, y, rm.env=F){
  df <- cbind(y, X)
  names(df) <- c("label", paste0("X", as.character(1:ncol(X))))
  f <- formula(label~1, data=df, env=emptyenv())
  if (rm.env){
    rm(list=c("df", "X", "y"))
  }
  print(pryr::object_size(f))
  return(f)
}

X <- matrix(rnorm(700*10000), ncol=700)
y <- rnorm(10000)

m <- test(X, y)
print(pryr::object_size(m))

m <- test(X, y, rm.env=T)
print(pryr::object_size(m))

结果,

672 B
168 MB
672 B
1.13 kB

请注意,第一次调用中的对象后面有 168 MB,因此一遍又一遍地调用第一个版本会很快吃掉大量内存。

formula(label~1, data=df, env=emptyenv()) 调用 S3 方法 formula.formula。我们来看看它的代码:

stats:::formula.formula
# function (x, ...)
# x

忽略多余的参数!

换句话说,您的作业与您只写 f = label ~ 1 相同。特别是,它的关联环境是本地环境,而不是空环境。要解决此问题,您需要手动重置它:

test <- function (X, y) {
  df <- cbind(y, X)
  names(df) <- c("label", paste0("X", seq_along(X)))
  # TODO: do something with `df` …
  f <- label ~ 1
  environment(f) <- emptyenv()
  f
}