1

I generate a series of plots stored in a matrix as part of a for loop much like in the MWE below. This same matrix also stores two other columns of information (Colour and Animal in this example). I then want to be able to create a grid of plots, where I identify the plot based on the corresponding Colour and Animal.

I tried creating a data frame and then using row names to call out the plots I needed, but had the common error of Cannot convert object of class list into a grob.. If I call from the matrix directly this works - however I want a way not have to do this in case the order of the data changes in the input files. Is it possible to work directly from the data frame? I've seen similar examples, but couldn't apply to my case. I want to stick with cow plot and change as little as possible in the data generation stage.

MWE

library(cowplot)
p <- vector('list', 15)
p <-
  matrix(
    p,
    nrow = 5,
    ncol = 3
  )

myColours = c("Yellow", "Red", "Blue", "Green", "Orange")
myAnimals = c("Kangaroo",  "Emu", "Echidna", "Platypus", "Cassowary")

x = seq(1,10)    
it = 1

for (i in seq(0,4)){ # generate example data and plots
  y = x^i
  t = runif(5)
  
  df <- data.frame("X" = x, "Y" = y, "T" = t)
  
  theanimal = myAnimals[i+1]
  thecolour = myColours[i+1]
        
  p[[it,1]] = thecolour
  p[[it,2]] = theanimal
          
  p[[it,3]] = ggplot(data = df, mapping = aes(x = X, y = Y)) +
    geom_point(aes(color = T)) +
    ggtitle(paste(thecolour, theanimal, sep = " "))
  
  it = it+ 1
}

# turn into df
pltdf<- as.data.frame(p)
colnames(pltdf) <- c("Colour", "Animal", "plot")
rownames(pltdf) <- do.call(paste, c(pltdf[c("Colour", "Animal")], sep="-"))

pltdf[[1,3]] # this is what I expect for a single plot

plot1 =  vector('list', 4)
plot1 <-
  matrix(
    plot1,
    nrow = 2,
    ncol = 2
  )

plot1[[1,1]] = pltdf["Red-Emu", "plot"]. # also tried with just plot[[1]] = etc.
plot1[[1,2]] = pltdf["Blue-Echidna", "plot"]

plot1[[2,1]] = pltdf["Orange-Cassowary", "plot"]
plot1[[2,2]] = pltdf["Green-Platypus", "plot"]


plot_grid(plotlist = t(plot1), ncol = 2)
plot_grid(plotlist = list(plot1), ncol = 2) # suggested solution on a dif problem

plot2 =  vector('list', 4) # what I want plots to look like in the end 
plot2[[1]] = p[[1,3]]
plot2[[2]] = p[[4,3]]
plot2[[3]] = p[[2, 3]]
plot2[[4]] = p[[5, 3]]

plot_grid(plotlist = t(plot2), ncol = 2)
Esme_
  • 1,360
  • 3
  • 18
  • 30
  • I am confused. What are you trying to do here? Do you want to store all the plots available in `pltdf$plot` in a 2 X 2 matrix? – Ronak Shah Feb 08 '21 at 04:28
  • I want to create the plot you get from `plot_grid(plotlist = t(plot2), ncol = 2)` but rather than having to manually set the row that the subplots are contained in, be able to use the row names from the data frame. This way, when the order of plots changes I don't need to go and redo all the row numbers. – Esme_ Feb 08 '21 at 04:58

1 Answers1

0

You can specify the order that you want the plots to be in and subset the dataframe accordingly which can be used in plot_grid.

library(cowplot)

order <- c("Red-Emu", "Blue-Echidna", "Orange-Cassowary", "Green-Platypus")
plot_grid(plotlist = pltdf[order, 'plot'], ncol = 2)
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213