Search code examples
rggplot2facet-grid

Pass arbitrary number of variables into facet_grid()


I'm trying to develop a function that will create a plot from just a few arguments. I need it to be flexible, so that I can input an unknown number of variables to facet the graph by. I've used all the quoting/unquoting methods I can find: {{ }}, .data[], !!!, inject, and more. I think part of the problem is that facet_grid calls it's variables within vars(), which is not cooperating with these operators. I have also tried passing the variables that I want to facet by into the function using dots, and by a named argument that takes a vector.

It seems to me that the best option here, based on this article (https://adv-r.hadley.nz/quasiquotation.html) is the unquote-splice operator. It seems to me like one of these should work, but neither does:

make_graph <- function (factor.by){
  ggplot(mpg, aes(cyl, cty)) + 
    geom_col() + 
    facet_grid(cols = vars(!!!factor.by))
}


make_graph(factor.by = c("manufacturer", "model"))


make_graph_2 <- function (...){
  ggplot(mpg, aes(cyl, cty)) + 
    geom_col() + 
    facet_grid(cols = vars(...))
}

make_graph_2("manufactuer", "model")

I would really appreciate any help figuring out how to make this work! I'm pretty new to programming with R, and I've been stuck on this issue for a long time. Thank you so much!


Solution

  • Some options:

    1. Ellipses:

      make_graph <- function(...) {
       ggplot(mpg, aes(cyl, cty)) + 
          geom_col() + 
          facet_grid(cols = vars(...))
      }
      make_graph(manufacturer, model)
      
    2. Programmatic formula:

      make_graph <- function(factor.by) {
       ggplot(mpg, aes(cyl, cty)) + 
          geom_col() + 
          facet_grid(rows = as.formula(paste0(". ~ ", paste(factor.by, collapse = "+"))))
      }
      make_graph(factor.by = c("manufacturer", "model"))
      
    3. Using ensyms (thank you @stefan!), for a variadic function:

      make_graph <- function(...) {
       ggplot(mpg, aes(cyl, cty)) + 
          geom_col() + 
          facet_grid(cols = vars(!!!rlang::ensyms(...)))
      }
      make_graph("manufacturer", "model")
      
    4. Using syms for a single-argument function:

      make_graph <- function(factor.by) {
       ggplot(mpg, aes(cyl, cty)) + 
          geom_col() + 
          facet_grid(cols = vars(!!!rlang::syms(factor.by)))
      }
      make_graph(c("manufacturer", "model"))