Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arrange multiple plots with ggarrange in for loop

Tags:

plot

r

I would like to arrange multiple plots in one image with the following code:

mydataframe <- data.frame(
  number1 = sample(1:140, size=200, replace=TRUE),
  number2 = sample(1:4000, size=200, replace=TRUE),
  number3 = sample(1:30, size=200, replace=TRUE),
  number4 = sample(1:200, size=200, replace=TRUE)
)

unit <- c(
  "number1" = "kmh", 
  "number2" = "rpm", 
  "number3" = "degrees", 
  "number4" = "volts"
)

labels <- c(
  "number1" = "Number 1", 
  "number2" = "Number 2", 
  "number3" = "Number 3", 
  "number4" = "Number 4"
)

for(key in names(unit))
{
  c_plot <- paste0 ("plot_", key) # generate new variable per plot
  
  assign (c_plot, # assign current plot to new variable
          
          ggplot(mydataframe, aes(x=key, y=eval(parse(text = key)))) +
            geom_boxplot() +
            labs (x = labels[key], y = unit[key]) +
            theme(axis.text.x = element_blank())
  )
  
  ggsave(filename = paste0("plots/", key, ".jpg"), plot = eval(parse(text = c_plot))) # save current plot as single image - that works
}

allplots <- ggarrange(plot_number1, plot_number2, plot_number3, plot_number4, # arrange all 4 plots - plot is always the last one generated
                      labels = c("A", "B", "C", "D"),
                      ncol = 2, nrow = 2)

allplots

As a result I get an image with 4 plots (what is correct), the label of x and y axis is correctly assigned (f.e. number1 for x and mph for y axis), but everything else is 4 times the last plot - the same data with same boxplots and the same y scales.

The strange thing is that the images saved with ggsave (which saves the current plot) is performed correctly - every single plot is created with the correct data and is different from all other plots.

Has anyone an idea what I do wrong? It seems that a specific part of the code in the for loop is not unified to the variable "c_plot" and is overwritten at the end of the loop, so in the end the data of the last plot is used for all plots.

like image 883
MDStat Avatar asked Dec 16 '25 13:12

MDStat


1 Answers

I was right. It's a lazy evaluation problem.

The "apply" family of functions, including, sapply, lapply and mapply, apply a function to series of values. See the online help.

Next time, please indicate which packages your code requires so that you provide a self-contained, reproducible example.

library(tidyverse)
library(ggpubr)

plotList <- lapply(
              names(unit),
              function(key) {
                # Need to assign the plot to a variable because 
                # you want to generate the plot AND save to file 
                x <- ggplot(mydataframe, aes(x=key, y=eval(parse(text = key)))) +
                       geom_boxplot() +
                       labs (x = labels[key], y = unit[key]) +
                       theme(axis.text.x = element_blank())
                # No need for the plot argument.  It defaults to the last plot created.
                ggsave(filename = paste0("plots/", key, ".jpg"))
                # Return the plot just created
                x
              }
)

allplots <- ggarrange(plotlist=plotList,
                      labels = c("A", "B", "C", "D"),
                      ncol = 2, nrow = 2)

allplots

Giving

enter image description here

like image 59
Limey Avatar answered Dec 19 '25 06:12

Limey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!