3

I want to combine dplyr and ggplot within one function using piping and struggling with some issues now.

Here is the first easy one which is working. Function which takes a dataframe and filters by a specified column and value.

foo <- function(df, y, t = 4){
  tmp <- df %>% 
          filter(!!enquo(y) > t)
  ggplot(tmp, aes_(substitute(y))) + 
      geom_histogram()  
}
foo(mtcars, cyl)

Now I'm trying to pipe directly to the ggplot function...gives an error

foo <- function(df, y, t=4){
  df %>% 
     filter(!!enquo(y) > t) %>% 
        ggplot(aes_(substitute(y))) + 
            geom_histogram()  
}
foo(mtcars, cyl)

Error in FUN(X[[i]], ...) : object 'cyl' not found In addition: Warning message: In FUN(X[[i]], ...) : restarting interrupted promise evaluation

and the last one. How to add a facet?

foo <- function(df, y, gr, t=4){
  df %>% 
       filter(!!enquo(y) > t) %>% 
  ggplot(aes_(substitute(y))) + 
      geom_histogram() +  
      facet_grid(~gr)
}
foo(mtcars, y= cyl, gr= vs)

Edit

The second issue can be solved using aes_q instead of aes_ & substitute. Source

foo <- function(df, y, gr, t=4){
  y <- enquo(y)
  df %>% 
    filter(!!y > t) %>% 
       ggplot(aes_q(y)) + 
           geom_histogram()
}
foo(mtcars, cyl)

Using ggplot2_2.2.1

2 Answers 2

4

ggplot2 v3.0.0 released in July 2018 supports !! (bang bang), !!!, and :=.

facet_wrap() and facet_grid() support vars() inputs. The first two arguments of facet_grid() become rows and cols. facet_grid(vars(cyl), vars(am, vs)) is equivalent to facet_grid(cyl ~ am + vs) and facet_grid(cols = vars(am, vs)) is equivalent to facet_grid(. ~ am + vs).

So your example can be modified as follow:

library(rlang)
library(tidyverse)

foo <- function(df, y, gr, t=4) {
  y <- enquo(y)
  gr <- enquo(gr)

  df %>% 
    filter(!!y > t) %>% 
    ggplot(aes(!!y)) + 
    geom_histogram() +  
    facet_grid(cols = vars(!!gr))
}

foo(mtcars, y= cyl, gr= vs)
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Created on 2018-04-04 by the reprex package (v0.2.0).

Sign up to request clarification or add additional context in comments.

Comments

2

@Tung's answer can be simplified using {{ syntax. https://rlang.r-lib.org/reference/quasiquotation.html

library(rlang)
library(dplyr)
library(ggplot2)

foo <- function(df, y, gr, t = 4) {
  df %>% 
    filter({{ y }}> t) %>% 
    ggplot(aes({{ y }})) + 
    geom_histogram() +  
    facet_grid(cols = vars({{ gr }}))
}

foo(mtcars, y = cyl, gr = vs)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.