首页 > 解决方案 > 返回保存时如何清理函数闭包(环境)?

问题描述

我有一个这样的计算(请注意,这只是非常简化的缩减版本,最小的可重现示例!):

computation <- function() # simplified version!
{
    # a lot of big matrices here....
    big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)

    exp.value <- 4.5
    prior <- function (x) rep(exp.value, nrow(x))

    # after computation, it returns the model
    list(
        some_info = 5.18,
        prior = prior
    )
}

此函数适合并返回一个模型,我想将其保存到磁盘:

m <- computation()
save(m, file = "tmp.Rdata")
file.info("tmp.Rdata")$size
# [1] 30713946

不幸的是,如您所见,文件太大,因为它包含函数的整个闭包prior(),而这个闭包包含computation()函数的所有数据,包括big_matrix(在我的完整代码中有很多数据)。

现在,我尝试通过使用以下方法重新定义先前函数的环境(闭包)来修复它environment(prior) <- list2env(list(exp.value = exp.value))

exp.value <- 4.5
environment(m$prior) <- list2env(list(exp.value = exp.value))
save(m, file = "tmp.Rdata")
file.info("tmp.Rdata")$size
# [1] 475

这按预期工作!不幸的是,当我将此清理代码放入计算()函数时(实际上,当我将此代码放入任何函数时),它停止工作!看:

computation <- function() # simplified version!
{
    # a lot of big matrices here....
    big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)

    exp.value <- 4.5
    prior <- function (x) rep(exp.value, nrow(x))
    environment(prior) <- list2env(list(exp.value = exp.value)) # this is the update

    # after computation, it returns the model
    list(
        some_info = 5.18,
        prior = prior
    )
}
m <- computation()
save(m, file = "tmp.Rdata")
file.info("tmp.Rdata")$size
# [1] 30713151

文件又大了,关闭没有正确清理。

  1. 我不明白这是怎么回事?为什么清理代码在任何函数之外运行时都在工作,而在函数中时停止工作?
  2. 如何让它在函数内部工作?

标签: rclosures

解决方案


解决问题的一种方法是在返回之前从环境中删除大变量。

computation <- function() 
{
    big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)

    exp.value <- 4.5
    prior <- function (x) rep(exp.value, nrow(x))

    rm(big_matrix) ## remove variable

    list(
        some_info = 5.18,
        prior = prior
    )
}

您的list2env方法的问题在于,默认情况下它指向当前环境作为新环境的父环境,因此无论如何您都在捕获函数内的所有内容。您可以改为将全局环境指定为基础环境

computation <- function() 
{
  big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)

  exp.value <- 4.5
  prior <- function (x) rep(exp.value, nrow(x))
                                                              # explicit parent
  environment(prior) <- list2env(list(exp.value = exp.value), parent=globalenv()) 

  list(
    some_info = 5.18,
    prior = prior
  )
}

(如果您指定emptyenv(),那么您将无法找到类似的内置函数rep()


推荐阅读