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

yfwxisqw  于 2023-01-10  发布在  其他
关注(0)|答案(2)|浏览(118)

RDS文件非常适合在R文件之间共享R对象,而且当我有一个特别复杂的布局时,我经常在R文件之间共享ggplot对象,通常这样做效果很好。
我的抱怨是,如果ggplot()函数调用包含一个全局变量,那么当你将绘图保存为.rds文件时,这个变量就会丢失,所以当你将绘图加载到一个新的R文件中时,信息就会丢失。
有人知道解决这个问题的聪明方法吗?我提出的解决方法很笨拙。而且我真的不想退回到默认的保存()和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

现在我将调色板指定为一个全局变量,并在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
fkvaft9z

fkvaft9z1#

这个问题已经很老了,但是...
可将绘图和全局变量另存为单独的对象:

# 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')

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

# 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
2izufjch

2izufjch2#

我认为一种选择是在一个新环境中创建绘图和绘图所需的所有对象。然后,您可以将此环境作为.Rds作为单个对象导出和导入。一旦导入到一个新会话中,您可以使用该环境,也可以将该环境的对象移动到全局环境中。
注意:此答案将在您的工作目录中创建文件

## Session 1 - when defining your plot, do this within a new environment 
e <- new.env()
## thanks https://stackoverflow.com/a/10761618/7941188
with(e, {
  set.seed(42)
  df <- data.frame(x = as.character(1:5), y = rnorm(5))
  col_pal <- c("red", "blue", "orange", "green", "purple")
  p <- ggplot(df, aes(x, y, fill = x)) + 
    geom_bar(stat = "identity") + 
    scale_fill_manual(values = col_pal)
})

saveRDS(e, "plot_and_obj.Rds")

## New session
library(ggplot2)
e <- readRDS("plot_and_obj.Rds")
## call plot either within the environment 
with(e, p)

## Or move all objects from child environment to global env 
## thanks https://stackoverflow.com/a/13797968/7941188
list2env(as.list(e), globalenv())
p

相关问题