返回并保存时如何清理函数关闭(环境)?

TMS*_*TMS 6 closures r

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

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
    )
}
Run Code Online (Sandbox Code Playgroud)

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

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

不幸的是,如您所见,该文件太大,因为它包含函数的整个闭包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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

该文件再次很大,关闭未正确清除。

  1. 我不明白这是怎么回事?为什么清理代码在任何函数外运行时起作用,而在函数内时停止工作?
  2. 如何使其在函数内工作?

MrF*_*ick 5

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

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
    )
}
Run Code Online (Sandbox Code Playgroud)

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
  )
}
Run Code Online (Sandbox Code Playgroud)

(如果您指定emptyenv(),则将无法找到诸如的内置函数rep()