代码之家  ›  专栏  ›  技术社区  ›  akraf

如何使用saverds(…,refhook=)参数?

  •  1
  • akraf  · 技术社区  · 5 年前

    我有一个复杂的列表对象,一个建模函数(asreml)的输出。该对象包含各种数据类型,包括函数和公式,这些类型都附加了环境。我不想把环境保存到rds中,因为它们很大,我保存了很多模型。

    我遇到了参数 refhook= serialize saveRDS 功能。文件上说:

    refhook函数可用于自定义对非系统引用对象(所有外部指针和弱引用,以及除命名空间和包环境和.globalenv之外的所有环境)的处理。序列化的hook函数应该为它想要处理的引用返回一个字符向量;否则它应该返回空值。

    给出了这个示例模型

    e <- new.env()
    e$a = rnorm(10)
    l <- list(a = e, b = 42)
    

    refhook函数确实显示了一些效果。当我定义一个返回字符的函数时,输出会变小,这表示环境不会被保存:

    length(serialize(l, connection = NULL))
    [1] 338
    
    s <- serialize(l, 
      connection = NULL, 
      refhook = function(x) "")
    length(s)
    [1] 109
    

    但是,我无法读取结果对象:

    unserialize(s)
    
    Error in unserialize(s) : 
      no restore method available
    

    我还尝试了一个原始向量输出,怀疑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
    

    如何使用 再勾= ?这个函数需要什么字符输出?

    1 回复  |  直到 5 年前
        1
  •  0
  •   akraf    5 年前

    啊,我自己发现的。错误“no restore method available”表示您忘记为 unserialize 功能。你们两个都需要,一个回扣 serialize 序列化 .

    反钩 串行化 在要返回的字符串中是完全自由的。唯一需要了解结果的是 序列化 .

    示例:序列化和还原包含集中存储的环境的列表

    生成环境存储库。让我们假装这些来自 外部源及其内容不需要序列化。恢复 它们,外部数据源只需要重新读取。

    repo <- list()
    for(i in 1:10){
      repo[[i]] <- new.env()
      repo[[i]]$a <- rnorm(1e6)
    }
    

    一个环境是8 MB大。我们不希望在序列化输出中包含所有这些数据,因为它已永久保存在 repo .

    object.size(repo[[1]]$a)
    

    这是我们要序列化的列表。它包含第二个环境 从存储库中。我们只想存储数值 b . 对于 环境,我们只想存储环境2 储存库。我们不想序列化内容,因为存储库 已经有了。

    l <- list(a = repo[[2]], b = 42)
    

    这是用于序列化的refhook。它在索引中查找环境 只存储索引。

    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)
    }
    

    非序列化的对应refhook获取索引并加载 相应的环境来自 回购协议 :

    unser <- function(s){
      i <- as.numeric(s)
      return(repo[[i]])
    }
    

    这样可以节省序列化输出中的大量空间

    • 不带自定义refhook:还包含环境

      object.size(serialize(l, con = NULL))
      ## 8000040 bytes
      
    • 使用自定义refhook:仅 l$b 并保存环境索引

      s <- serialize(l, con = NULL, refhook = ser)
      object.size(s)
      ## 168 bytes
      

    当取消序列化时,将从数据库加载环境。

    u <- unserialize(s, refhook = unser)
    ## $a
    ## <environment: 0x000000001c91a118>
    ## 
    ## $b
    ## [1] 42