我有一个复杂的列表对象,一个建模函数 (asreml) 的输出。该对象包含各种数据类型,包括附加了环境的函数和公式。我不想将环境保存到 RDS,因为它们非常大而且我保存了很多模型。
我refhook=在serialize和saveRDS函数中遇到了参数。文档说:
refhook 函数可用于自定义非系统引用对象(所有外部指针和弱引用,以及命名空间和包环境以及 .GlobalEnv 以外的所有环境)的处理。serialize 的钩子函数应该为它要处理的引用返回一个字符向量;否则它应该返回NULL。
鉴于此示例模型
e <- new.env()
e$a = rnorm(10)
l <- list(a = e, b = 42)
Run Code Online (Sandbox Code Playgroud)
refhook 函数确实显示了一些效果。当我定义一个返回字符的函数时,输出变小,表明环境没有得到保存:
length(serialize(l, connection = NULL))
[1] 338
s <- serialize(l,
connection = NULL,
refhook = function(x) "")
length(s)
[1] 109
Run Code Online (Sandbox Code Playgroud)
但是,我无法读取结果对象:
unserialize(s)
Error in unserialize(s) :
no restore method available
Run Code Online (Sandbox Code Playgroud)
我还尝试了原始向量输出,怀疑 refhook 可能会提供替代的序列化输出,但这不起作用:
s2 <- serialize(l,
connection = NULL,
refhook = function(x)
serialize("env", connection = NULL)))
Error in serialize(l, con = NULL, refhook = function(x) serialize("env", :
assertion 'TYPEOF(t) == STRSXP && LENGTH(t) > 0' failed: file 'serialize.c', line 982
Run Code Online (Sandbox Code Playgroud)
我如何使用refhook=?这个函数期望输出什么字符?
啊,我自己发现了。错误“没有可用的恢复方法”意味着您忘记为该unserialize函数添加重新挂钩。你需要两个,重新挂接serialize和unserialize。
serialize在返回什么字符串中的 refhook是完全自由的。唯一需要了解结果的是unserialize.
生成环境存储库。让我们假设这些来自外部源并且它们的内容不需要被序列化。要恢复它们,只需重新读取外部数据源。
repo <- list()
for(i in 1:10){
repo[[i]] <- new.env()
repo[[i]]$a <- rnorm(1e6)
}
Run Code Online (Sandbox Code Playgroud)
一种环境是 8 MB 大。我们不想在序列化输出中包含所有这些数据,因为它已经永久保存在repo.
object.size(repo[[1]]$a)
Run Code Online (Sandbox Code Playgroud)
这是我们要序列化的列表。它包含存储库中的第二个环境。我们只想存储数值b。对于环境,我们只想存储它是存储库中的环境 2。我们不想序列化内容,因为存储库已经有了它们。
l <- list(a = repo[[2]], b = 42)
Run Code Online (Sandbox Code Playgroud)
这是序列化的重新挂钩。它在索引中查找环境并只存储索引。
ser <- function(e){
for(i in seq_along(repo)){
if(identical(e, repo[[i]])){
message("Identified environment #",i)
return(as.character(i)) # Just save the
}
}
message("Environment not found in the repository")
return(NULL)
}
Run Code Online (Sandbox Code Playgroud)
反序列化的相应 refhook 获取索引并从repo以下位置加载相应的环境:
unser <- function(s){
i <- as.numeric(s)
return(repo[[i]])
}
Run Code Online (Sandbox Code Playgroud)
这在序列化输出中节省了大量空间
没有自定义 refhook:也包含环境
object.size(serialize(l, con = NULL))
## 8000040 bytes
Run Code Online (Sandbox Code Playgroud)使用自定义 refhook:只l$b保存和环境索引
s <- serialize(l, con = NULL, refhook = ser)
object.size(s)
## 168 bytes
Run Code Online (Sandbox Code Playgroud)反序列化时从数据库加载环境
u <- unserialize(s, refhook = unser)
## $a
## <environment: 0x000000001c91a118>
##
## $b
## [1] 42
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
873 次 |
| 最近记录: |