Home > database >  How to combine two plot lists (made of ggplot graphs) in a single plot list?
How to combine two plot lists (made of ggplot graphs) in a single plot list?

Time:06-25

I have two plot lists, each one with 3 graphs, made with ggplot:

plot_list1: enter image description here

plot_list2: enter image description here

I would like to combine them in a single list, where all graphs are present, as this one:

enter image description here

I have thought to create plot_list1 as you see above, and plot_list2 with transparent background, as follows: enter image description here

and add them in this way:

for(i in 1:3)
{
plot_list[[i]] <- plot_list1[[i]]   plot_list2[[i]]  
}

But it gives me the error message: Error in ggplot_add(): ! Can't add plot_list2[[i]] to a ggplot object.

How could I do?

Hereafter my complete code:

double_plot <- function()

{
x1 <- c(1, 2, 3, 4, 5)
y1 <- c(10, 20, 30, 40, 50)
x2 <- c(2, 4, 6, 8, 10)
y2 <- c(15, 20, 25, 30, 35)
x3 <- c(1, 2, 3, 4, 5)
y3 <- c(20, 40, 60, 80, 100)

x4 <- c(1, 2, 3, 4, 5)
y4 <- c(13, 23, 33, 43, 53)
x5 <- c(2, 4, 6, 8, 10)
y5 <- c(15, 35, 55, 75, 95)
x6 <- c(1, 2, 3, 4, 5)
y6 <- c(35, 40, 45, 50, 55)

df1 <- data.frame(x1, y1, x2, y2, x3, y3)
df2 <- data.frame(x4, y4, x5, y5, x6, y6)

n <- ncol(df1)
m <- nrow(df1)

plot_list1 <- list()
plot_list2 <- list()

for(i in 1:(n/2))
{
  p <- i (i-1)
  
  datax <- df1[,p]
  datay <- df1[,p 1]
  
  data <- cbind(datax, datay)
  data_df <- as.data.frame(data)

  plot_list1[[i]] <- ggplot(data_df, aes(x=datax, y=datay))  
    geom_point(size = 4)  
    geom_line(color="red", size = 2)  
    xlim(0, 10)  
    ylim(0, 100)    
}


for(i in 1:(n/2))
{
  p <- i (i-1)

  datax <- df2[,p]
  datay <- df2[,p 1]
  
  data <- cbind(datax, datay)
  data_df <- as.data.frame(data)
  
  plot_list2[[i]] <- ggplot(data_df, aes(x=datax, y=datay))  
    geom_point(size =4)  
    geom_line(color="blue", size =2)  
    theme(
      panel.background = element_rect(fill = "transparent",colour = NA), 
      panel.grid.minor = element_blank(), 
      panel.grid.major = element_blank())  
    xlim(0, 10)  
    ylim(0, 100)   
}

for(i in 1:(n/2))
{
 plot_list[[i]] <- plot_list1[[i]]   plot_list2[[i]]  # if you comment this line and modify (in the next one) arrangeGrob(grobs=plot_list... in arrangeGrob(grobs=plot_list1 or grobs=plot_list2, you will obtain the two different plot lists.
}

ggsave(width = 30, height = 10, dpi = 300, file = "test.pdf", arrangeGrob(grobs=plot_list, ncol = 3))

dev.off() 
}

CodePudding user response:

Your current code adds ggplot() ... ggplot() .....

There should really only be one ggplot call. Then you add other lines of code to that ggplot call.

You can fix this by removing the ggplot() call in the second loop

Your code then looks something likes this:

  for(i in 1:(n/2))
  {
    p <- i (i-1)
    
    datax <- df1[,p]
    datay <- df1[,p 1]
    
    data <- cbind(datax, datay)
    data_df <- as.data.frame(data)
    
    plot_list1[[i]] <- ggplot(data_df, aes(x=datax, y=datay))  
      geom_point(size = 4)  
      geom_line(color="red", size = 2)   
  }
  
  
  for(i in 1:(n/2))
  {
    p <- i (i-1)
    
    datax <- df2[,p]
    datay <- df2[,p 1]
    
    data <- cbind(datax, datay)
    data_df <- as.data.frame(data)
    
    plot_list2[[i]] <- plot_list1[[i]]   geom_point(data = data_df, aes(x=datax, y=datay), size =4)  
      geom_line( data = data_df, aes(x=datax, y=datay), color = "blue", size =2) 
      theme(
        panel.background = element_rect(fill = "transparent",colour = NA), 
        panel.grid.minor = element_blank(), 
        panel.grid.major = element_blank())  
      xlim(0, 10)  
      ylim(0, 100)
  }  
  
  plot_list <- list()
  
  for(i in 1:(n/2))
  {
    plot_list[[i]] <- plot_list2[[i]]  # if you comment this line and modify (in the next one) arrangeGrob(grobs=plot_list... in arrangeGrob(grobs=plot_list1 or grobs=plot_list2, you will obtain the two different plot lists.
  }

enter image description here

CodePudding user response:

If you want your lines from both datasets in one plot I would suggest to simply use one call to ggplot instead of trying to somehow overlay one by the other. To this end use the same names for both dataframes and bind them together using e.g. dpylr::bind_rows. Also, instead of looping over columns I would suggest to convert your data to long format using e.g. tidyr::pivot_longer. After doing you could easily loop over your data using lapply to create your plots:

library(dplyr)
library(ggplot2)
library(tidyr)

names(df2) <- names(df1)

df <- list(df1, df2) |>
  bind_rows(.id = "df_id") |>
  pivot_longer(-df_id, names_to = c(".value", "id"), names_pattern = "^(x|y)(.*)$")

plot_fun <- function(.data) {
  ggplot(.data, aes(x = x, y = y))  
    geom_point(size = 4)  
    geom_line(aes(color = df_id), size = 2)  
    scale_color_manual(values = c("red", "blue"))  
    xlim(0, 10)  
    ylim(0, 100)
}

split(df, df$id) |>
  lapply(plot_fun) |>
  gridExtra::grid.arrange(grobs = _, ncol = 3)

A second and my personally preferred option would be to simply use faceting:

plot_fun(df)   facet_wrap(~id)

enter image description here

  • Related