2

I'm making many plots by nesting my dataset and mapping over it. Ultimately, I want to put these plots into a PowerPoint deck using officer. I can make the plots, but for some reason, when I nest and map over it, R categorizes each plot as a list instead of a plot. It will print them just fine (so my problem is different than the one here), but to integrate with officer, I need the object to be a ggplot (unless anyone knows a way to override this requirement of ph_with's value argument...).

When I try as_ggplot(my_plot), I get

Error in gList(...) : only 'grobs' allowed in "gList"

I also tried ggplotGrob(my_plot), as suggested here, but that also didn't work, yielding Error in UseMethod("ggplot_build") : no applicable method for 'ggplot_build' applied to an object of class "list".

Below is a reproducible example comparing creating the plot via nest/map versus traditional means:

library(purrr)
library(dplyr)
library(ggplot2)
library(tidyr)
#Nest my data by cyl
mt_nest <- mtcars %>%
  nest(data = !(cyl))

#Make all plots separated by cyl (generates 3 plots--one for each cyl)
mt_plots <- mt_nest %>%
  mutate(plots = map(
    .x = data, 
    ~ggplot(.x, aes(x = gear, y = mpg)) +
      geom_col()))

#Pulls out just one of the plots
one_plot_from_nest <- mt_plots$plots[mt_plots$cyl == 6]

#Plot prints correctly
one_plot_from_nest

#Class is showing list though
class(one_plot_from_nest)

#Why can't I force the plot to be a ggplot object?
as_ggplot(one_plot_from_nest)

#Make the same plot as above
one_plot <- mtcars %>%
  filter(cyl == 6) %>%
  ggplot(aes(x = gear, y = mpg)) +
  geom_col()

#Also prints correctly
one_plot

#This is a ggplot object
class(one_plot)
J.Sabree
  • 2,280
  • 19
  • 48

1 Answers1

3

We need to extract the list element - as it is a list of length 1

length(one_plot_from_nest)
[1] 1

class(one_plot_from_nest[[1]])
[1] "gg"     "ggplot"

The reason is that while subsetting we are using [ for a list column i.e. plots and [ still returns the list, whereas if we use [[ it will extract the list element

mt_plots$plots[mt_plots$cyl == 6]

Edit By Original Poster

Adding onto Akrun's post to explicitly show how to combine the two portions and expand it, if you want to explicitly call for a plot like I did (e.g., mt_plots$plots[mt_plots$cyl == 6]) rather than just an index that could change, you can combine Akrun's and my approach to guarantee a specific ggplot object:

plot_6 <-mt_plots$plots[mt_plots$cyl == 6][[1]]

class(plot_6)
[1] "gg"     "ggplot"

This guarantee that you'll get the correct plot each time with [[1]] assumes you only have one plot for cyl (which you would with the code I used). However, if you had multiple for cyl == 6 (perhaps you nested by cyl and vs, you could always expand it:

plot_6 <-mt_plots$plots[mt_plots$cyl == 6 & vs == 0][[1]]
J.Sabree
  • 2,280
  • 19
  • 48
akrun
  • 874,273
  • 37
  • 540
  • 662