Extracting a ggplot from a list of ggplots

IrisPlots <- iris %>% ## Creates a list of bar plots, one for each species.
  group_by(Species) %>%
  do(plots = ggplot(data = .) +
       aes(x = Sepal.Length) + 
       geom_bar() + 
       labs(title = .$Species))
IrisPlots$plots[1] ## Prints the first plot from the list
class(IrisPlots$plots[1]) ## shows the class of the object

So here is where I found the problem. The do() process stripped the "gg" and "ggplot" class from each of the objects within the list. This isn't an issue if I wanted to print each one individually, but if I want to combine them (I do), ggarrange() can't handle the "list" objects.

SingleIrisPlot <- ggplot(data = iris,
                         aes(x = Sepal.Length, y = Sepal.Width, colour = factor(Species))) + 
  geom_point()
SingleIrisPlot
class(SingleIrisPlot)

This creates a second plot to join with ggarrange.

ggarrange(IrisPlots$plots[1],SingleIrisPlot)

This throws an error. Is there a way to reattach the class of "gg" or "ggplot" or a way to restructure the do() call?

You need to access the plots with [[]], not [].

class(IrisPlots$plots[[1]])
#> [1] "gg"     "ggplot"
6 Likes

This is why a little bit of knowledge is a dangerous thing!

Thanks so much!

Admittedly, it can be a bit startling that [] applied to a list always returns the element you asked for wrapped in a list, since your expectations may have been set by applying [] to atomic vectors, where [] often appears to do the same thing as [[]] (in fact, they still differ: using [[]] on a named atomic vector drops the names).

The unifying concept here is that some subsetting methods simplify the result if possible, whereas others preserve the data type (e.g., a list remains a list, rather than suddenly turning into whatever the contents of the list element is).

If you want to upgrade your subsetting knowledge, this is a good starting place:
http://adv-r.had.co.nz/Subsetting.html

3 Likes