Explanation of the problem
I have extensive if, else if, loops that produce graphs in ggplot2. Each graph gets stored with a unique object name, with the following pattern:
graph_log_bar_blue <-
graph_log_violin_blue <-
graph_log_bar_red <-
graph_log_violin_red <-
graph_log_bar_green <-
graph_log_violin_green <-
etc...
I wish to store the graphs that are created (the ones that satisfy the loop conditions), in a list, so that I can arrange them with either ggarrange (in ggpubr) or with gridExtra.
graph_list <- ls(pattern = "graph_") #list names of graphs (but doesn't store the graph in the list)
library("ggpubr")
ggarrange(graph_list,
nrow = 1, ncol = 3)
# OR
library("gridExtra") # Load gridExtra
do.call("grid.arrange", c(plot_list, ncol = 3))
Question
How do I:
- Create a list of graphs produced by ggplot (is this possible?)
- How can I select/make a list of graphs produced inside an if/else loop?
- How do I call graphs produced to then arrange them as a panel figure using ggarrange etc (ggpubr package)?
DATA
using the iris data set. The if loops do not make logical sense, it is just a mock of the structure of loop I am using, take it with a grain of salt :/
library(ggplot2)
iris <- iris
#Dataset 1
kt <- kruskal.test(Petal.Width ~ Species, data = iris)
kt$p.value
if(kt$p.value > 0.05){
pt <- pairwise.wilcox.test(iris$Petal.Width, g=iris$Species, p.adjust.method = "BH")
}else if(kt$p.value < 0.05){
graph_log_bar_blue <- ggplot(data = iris, aes(y=Petal.Width, x=Species, fill = Species))
stat_summary(fun = median, show.legend = FALSE, geom="crossbar")
geom_jitter(show.legend = FALSE, width = 0.25, shape = 21, colour = "black", size = 2.5)
labs(x=NULL, y= "Petal Width (cm)")
}else{
graph_log_violin_blue <- ggplot(data = iris, aes(y=Petal.Width, x=Species, fill = Species))
geom_violin(show.legend = FALSE, trim = FALSE, adjust = 0.6)
labs(x=NULL,
y= "Petal Width (cm)")
}
#dataset 2
kt_sep <- kruskal.test(Sepal.Width ~ Species, data = iris)
kt_sep$p.value
if(kt_sep$p.value > 0.05){
pt_sep <- pairwise.wilcox.test(iris$Sepal.Width, g=iris$Species, p.adjust.method = "BH")
}else if(kt_sep$p.value > 0.05){
graph_log_bar_red <- ggplot(data = iris, aes(y=Sepal.Width, x=Species, fill = Species))
stat_summary(fun = median, show.legend = FALSE, geom="crossbar")
geom_jitter(show.legend = FALSE, width = 0.25, shape = 21, colour = "black", size = 2.5)
labs(x=NULL, y= "Sepal Width (cm)")
}else{
graph_log_violin_red <- ggplot(data = iris, aes(y=Sepal.Width, x=Species, fill = Species))
geom_violin(show.legend = FALSE, trim = FALSE, adjust = 0.6)
labs(x=NULL,
y= "Sepal Width (cm)")
}
graph_list <- ls(pattern="graph_")
Where do I go from here to arrange both graphs together!
CodePudding user response:
You could create your plot_list
using e.g.
plot_list <- lapply(grep("^graph_", ls(), value = TRUE), get)
Afterwards you could pass the list to the plotlist
argument of ggpubr::ggarrange
, i.e.
ggpubr::ggarrange(plotlist = plot_list)
A minimal reprex of this approach using some fake plots:
library(ggplot2)
library(ggpubr)
graph_log_bar_blue <- ggplot()
graph_log_violin_blue <- ggplot()
plot_list <- lapply(grep("^graph_", ls(), value = TRUE), get)
ggpubr::ggarrange(plotlist = plot_list)
However, instead of storing your graphs as single objects I would suggest to create a list
of plots from start. Additionally, instead of using copy and paste to create your charts it might be worthwhile to write a small custom function to perform your tests and create the charts. Such an approach may look like so:
library(ggplot2)
library(ggpubr)
plot_fun <- function(.data, x, y, ylab) {
kt <- kruskal.test(.data[[y]] ~ .data[[x]])
if (kt$p.value > 0.05) {
pt <- pairwise.wilcox.test(.data[[y]], g = .data[[x]], p.adjust.method = "BH")
plot <- NULL
} else {
pt <- NULL
base <- ggplot(.data, aes(.data[[x]], .data[[y]], fill = .data[[x]]))
labs(x = NULL, y = ylab)
plot <- if (kt$p.value < 0.05) {
base
stat_summary(fun = median, show.legend = FALSE, geom="crossbar")
geom_jitter(show.legend = FALSE, width = 0.25, shape = 21, colour = "black", size = 2.5)
} else {
base
geom_violin(show.legend = FALSE, trim = FALSE, adjust = 0.6)
}
}
# Return test results and plot as list
list(kt = kt, pt = pt, plot = plot)
}
p_list <- list(
plot_fun(iris, "Species", "Petal.Width", "Petal Width (cm)"),
plot_fun(iris, "Species", "Sepal.Width", "Sepal Width (cm)")
)
# Get the plots
plots <- lapply(p_list, function(x) x[["plot"]])
ggpubr::ggarrange(plotlist = plots)