【问题标题】:How to serialize/deserialize ggplot object for use with mongodb in R如何序列化/反序列化 ggplot 对象以在 R 中与 mongodb 一起使用
【发布时间】:2017-08-28 22:53:54
【问题描述】:

我有这个代码:

for(plot in plotResults) {
  .session$plots[[plot$id]] <- if (!is.null(plot[["grob"]])) {
    plot[["grob"]]
  } else {
    plot[["plot"]]
  }
  ggsave(paste0(plot$id, ".png"), .session$plots[[plot$id]])
  ...

}

文件已生成,但是当我使用此工具将 ggplot 对象保存到 mongo 时:

serializeObj <- function(obj) {
  if (is.list(obj)) {
    structure(lapply(obj, serializeObj), names = serializeNames(obj))
  } else {
    rawToChar(serialize(obj, NULL, ascii = TRUE))
  }
}

deserializeObj <- function(obj) {
  if (is.list(obj)) {
    structure(lapply(obj, deserializeObj), names = unserializeNames(obj))
  } else if (is.serialized(obj)) {
    unserialize(charToRaw(obj))
  } else {
    obj
  }
}

## Replaces characters illegal in Mongo names with "safe" substitutes
safeNames <- function(value) {
  gsub("\\.", "___DOT___", value)
}

## Replaces back "safe" substitutes
unsafeNames <- function(value) {
  gsub("___DOT___", ".", value)
}

serializeNames <- function(obj) {
  lapply(names(obj), safeNames)
}

unserializeNames <- function(obj) {
  lapply(names(obj), unsafeNames)  
}

我在保存到 mongo 之前运行 serializeObj,然后在从 mongo 读取后运行 deserializeObj。在读取而不是 ggplot 对象后,我得到了列表,我无法在该列表上调用 ggsave。

如何序列化某种类型的对象,例如 ggplot,然后反序列化它以获得相同的对象?

【问题讨论】:

  • ggplot 是一个(嵌套的)列表。使用str 进行检查。您的方法会丢失属性,最重要的是类属性。
  • @Roland 有没有办法恢复类属性?
  • help("attr"),help("attributes"),当然需要先存储。否则,我们将讨论一些子列表属性的手动工作。

标签: r mongodb serialization ggplot2


【解决方案1】:

这项工作,而不是递归序列化器/反序列化器,只需要一个级别,也不需要序列化名称,因为它们不再有点,只有嵌套的绘图数据有它们。

serializePlots <- function(data) {
  lapply(data, function(plot) {
    rawToChar(serialize(plot, NULL, ascii = TRUE))
  })
}

unserializePlots <- function(data) {
  lapply(data, function(obj) {
    if (is.serialized(obj)) {
      unserialize(charToRaw(obj))
    } else {
      obj
    }
  })
}

【讨论】:

    【解决方案2】:

    正如您的 cmets 所指出的,您正在丢失有关 ggplot 对象的类的信息。您可能应该确保存储此信息并在反序列化时恢复它。例如,我写了三个简单的 f(x) 可能会有所帮助。

    #### custom f(x)    
    serializeGGClasses <- function(obj) {
      serializeObj(sapply(obj, class))
    }
    
    unserializeGGClasses <- function(obj) {
      lapply(obj, (function(el) {unserialize(charToRaw(el)) } ))
    }
    
    restoreGGClasses <- function(plot.obj, class.obj) {
      class(plot.obj) <- c("gg", "ggplot")
      for (i in 1:length(plot.obj)) {
       class(plot.obj[[i]]) <- class.obj[[i]] 
      }
      return(plot.obj)
    }
    
    ###
    

    现在,您可以序列化 ggplot 对象的所有类并将它们存储在您的数据库中。当您检索对象时,您需要恢复它们

    library(ggplot2)    
    a<- qplot(1, 1)
    class(a)     # "gg"     "ggplot"
    is.list(a)   # TRUE
    
    b <-  serializeObj(a)
    b.class <- serializeGGClasses(a)
    
    # Unserialize
    c <- deserializeObj(b)
    c.class <- unserializeGGClasses(b.class)
    
    # Right now, "c" is just a list
    final.c <- restoreGGClasses(plot.obj = c, 
                                class.obj = c.class)
    
    # "final.c" can be plotted
    final.c
    

    【讨论】:

    • 不幸的是这不起作用,反序列化后情节混乱了。递归方法是错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 2022-12-14
    • 2019-06-03
    • 2019-03-09
    相关资源
    最近更新 更多