是否可以在 ggplot() 调用中使用全局变量以 RDS 格式保存 ggplot?

ran*_*ies 6 r ggplot2

RDS 文件非常适合在 R 文件之间共享 R 对象。当我有一个特别复杂的布局时,我经常在 R 文件之间共享 ggplot 对象。通常这效果很好。

我的抱怨是,如果您的 ggplot() 函数调用包含全局变量,则当您将绘图保存为 .rds 文件时,该变量会丢失。因此,当您将绘图加载到新的 R 文件中时,这可不是好事。信息丢失。

有谁知道这个问题的巧妙解决方案?我想出的解决方法很笨拙。我真的不想回归到默认的 save() 和 load() 函数。

举几个例子怎么样。我将从一个有效的块开始。然后我将展示全局变量如何导致事情崩溃。

注意:此代码将在您当前的工作目录中放置一些垃圾文件。你们要被警告。

# Preliminaries -------------------------------------------
library(tibble)
library(magrittr)
library(ggplot2)

# Fake data
x <- 1:5 %>% as.factor()
y <- rnorm(5)
df <- data_frame(x, y)


# First an example that works -----------------------------
# Notice how the color palette is 
# defined within scale_fill_manual()
this_plot_works <- ggplot(df, aes(x, y, fill = x)) + 
  geom_bar(stat = "identity") + 
  scale_fill_manual(values = c("red", "blue", "orange", "green", "purple"))

# Save plot to file
saveRDS(this_plot_works, file = "this_plot_works.rds")

# To simulate the behavior of moving to a new R file
# let's remove the ggplot object from the environment.
rm(this_plot_works)

# Now, pretending we're in a new R file, load the plot
this_plot_works_reloaded <- readRDS("this_plot_works.rds")
this_plot_works_reloaded
Run Code Online (Sandbox Code Playgroud)

现在我将把调色板指定为全局变量,并在 ggplot 函数中调用它(我猜,从技术上讲,它是在“scale_fill_manual()”函数中调用的,但你知道我的意思)。这个策略不会起作用。

# Second example that won't work --------------------------
# Specify color palette as a global variable
col_pal <- c("red", "blue", "orange", "green", "purple")

# Plot
# Note that the color palette is tied to the global variable
this_plot_wont_work <- ggplot(df, aes(x, y, fill = x)) + 
  geom_bar(stat = "identity") + 
  scale_fill_manual(values = col_pal) 

# Save the plot to file
saveRDS(this_plot_wont_work, file = "this_plot_wont_work.rds")

# Again, let's remove the key global variables
# and pretend we're switching to a new R file
rm(this_plot_wont_work, col_pal)

# Load the plot
this_plot_wont_work_reloaded <- readRDS("this_plot_wont_work.rds")
this_plot_wont_work_reloaded
Run Code Online (Sandbox Code Playgroud)

小智 1

这个问题很老了,但无论如何......

您可以将绘图和全局变量保存为单独的对象:

# SAVE PLOT...
saveRDS(this_plot_wont_work, file = 'this_plot_wont_work.rds')

# ...AND GLOBAL VARIABLES
globVar = list(col_pal = col_pal)
saveRDS(globVar, file = 'this_plot_wont_work.bis.rds')
Run Code Online (Sandbox Code Playgroud)

然后以正确的顺序重新加载它们(即首先加载全局变量)

# LOAD GLOBAL VARIABLES RDS NAMED LIST
globRDS = 'this_plot_wont_work.bis.rds'
gglob   = readRDS(globRDS)

# TURN ELEMENTS INTO ACCESSIBLE VARIABLES SO GGPLOT2 HAVE ACCESS TO THEM
# (I.E. LIST(VAR1 = VALUE1) >>> VAR1 = VALUE1)
for (i in seq(length(gglob))){
    assign(x = names(gglob[i]) , value = gglob[[i]])
}

# AND FINALLY LOAD THE GGPLOT OBJECT
plotRDS = 'this_plot_wont_work.rds'
gg = readRDS(plotRDS)

gg
Run Code Online (Sandbox Code Playgroud)