rggplot2purrrr-factor

In R, why does map make the wrong plot, but the same code works when I do not map?


I want to map a ggplot over a pre-set vector of x variables. The code does generate the plots, but it looks wrong when I use map()--it collapses all the factors into one group. However, this does not happen when I do not use map. Why is this happening? I explicitly call for these variables to be a factor:

library(dplyr)
library(purrr)
library(ggplot2)
library(stringr)


data('mtcars')

#Define x variables to iterate over
x_variables <- c("cyl", "vs", "am", "gear", "carb")

#Create function

make_chart <- function(data, x, y){
  
  require(stringr)
  
  x_title <- str_to_title(rlang::as_name(enquo(x)))
  
  ggplot(data, aes(x = as.factor({{x}}), y = {{y}})) +
    geom_col() +
    ggtitle(paste0("Number of ", x_title, " by MPG")) +
    xlab(x_title)
  
}

#This runs--but collapses results across factors
  map(.x = x_variables,
      ~mtcars %>%
        make_chart(x = .x, y = mpg))
  
  #This looks right
  make_chart(data = mtcars, x = gear, y = mpg)

Solution

  • You could use do.call here, ensuring to wrap your .x variable in ensym:

    plot_list <- map(.x = x_variables,
                     ~ do.call(make_chart, 
                        list(data = mtcars, x = rlang::ensym(.x), y = quote(mpg))))
    

    So, for example, to plot all the generated images at once, we can do:

    library(patchwork)
    
    (plot_list[[1]] + plot_list[[2]]) / 
      (plot_list[[3]] + plot_list[[4]] + plot_list[[5]])
    

    Created on 2023-03-02 with reprex v2.0.2