Hi CLH
Hi CLH

Reputation: 49

Tidy evaluation in making multiple panel plots using ggplot2

I have a function to make multi-panel plots using ggplot2:

plot_facet <- function(df, var.x, var.y, var.facet) {
  p <- df %>% 
    ggplot(aes(x = {{var.x}}, y = {{var.y}})) +
    geom_point()    
  
   if(!is_missing(var.facet)) p <- p + facet_grid({{var.facet}} ~ .)
  
  return(p)
}

The following call works as expected:

plot_facet(mtcars, mpg, hp) + facet_grid(cyl ~ .)

But this doesn't:

plot_facet(mtcars, mpg, hp, cyl)

and I got the error message:

Error in is_reference(x, quote(expr = )) : object 'cyl' not found

I have tried this and it doesn't work either:

facet_grid(rows = vars({{var.facet}}))

How can I fix it? Thanks for your help.

Upvotes: 3

Views: 126

Answers (2)

starja
starja

Reputation: 10365

The problem seems to be that is_missing evaluates too much (to be honest, I don't make too much sense out of its help page). If you just use missing (which only operates on the symbol), you can use your facet_grid(rows = vars({{var.facet}})) approach:

library(ggplot2)
library(magrittr)
library(rlang)

plot_facet <- function(df, var.x, var.y, var.facet) {
  p <- df %>% 
    ggplot(aes(x = {{var.x}}, y = {{var.y}})) +
    geom_point()    
  
  if(!missing(var.facet)) p <- p + facet_grid(rows = vars({{var.facet}}))
  
  return(p)
}

plot_facet(mtcars, mpg, hp, cyl)

Alternatively, you can convert var.facet to a symbol at the beginning of your function and use this together with is_missing and the rows argument:

plot_facet <- function(df, var.x, var.y, var.facet) {
  var.facet <- ensym(var.facet)
  p <- df %>% 
    ggplot(aes(x = {{var.x}}, y = {{var.y}})) +
    geom_point()    
  
  if(!is_missing(var.facet)) p <- p + facet_grid(rows = vars({{var.facet}}))
  
  return(p)
}

plot_facet(mtcars, mpg, hp, cyl)

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388982

You can try this approach :

library(ggplot2)

plot_facet <- function(df, var.x, var.y, var.facet) {
  var <- deparse(substitute(var.facet)) 
  p <- df %>% 
    ggplot(aes(x = {{var.x}}, y = {{var.y}})) +
    geom_point()    
  
  if(var != '') p <- p + facet_grid(reformulate('.', var))
  
  return(p)
}

The both of this works and produces the same output.

plot_facet(mtcars, mpg, hp) + facet_grid(cyl ~ .)
plot_facet(mtcars, mpg, hp, cyl)

Upvotes: 1

Related Questions