3
votes

I often combine dplyr with ggplot2 in wrapper functions for analysis. As I am moving to the new NSE / SE paradigm of v.0.7.1 with tidyeval, I am struggling to get this combination to work. I found that ggplot does not understand unquoted quosers (yet). The following does not work:

example_func <- function(col) {
  col <- enquo(col)
  mtcars %>% count(!!col) %>% 
    ggplot(aes((!!col), n)) +
    geom_bar(stat = "identity")
}
example_func(cyl)
# Error in !col : invalid argument type

I currently use the following work-around. But I assume there must be a better way.

example_func2 <- function(col) {
  col <- enquo(col)
  mtcars %>% count(!!col) %>% 
    ggplot(aes_string(rlang::quo_text(col), "n")) +
    geom_bar(stat = "identity")
}

Please show me what the best way to combine these two. Thanks!

2
If it is a string, you need aes_string, What is the issue with that one? - akrun
It feels like a big detour, quoting, then using quo_text, then using aes_string. Hoped there was a more straightforward solution. - Edwin
Yet, this seems to be the way to go when using tidyeval. - lukeA

2 Answers

3
votes

If you are already handling quosures it's easier to use aes_ which accepts inputs quoted as a formula: aes_(col, ~n).

This bit of code solves your problem:

library(tidyverse)
example_func <- function(col) {
  col <- enquo(col)
  mtcars %>% count(!!col) %>% 
    ggplot(aes_(col, ~n)) +
    geom_bar(stat = "identity")
}

example_func(cyl)
2
votes

There seem to be two ways of thinking about this.

Approach 1: Separation of concerns.

I like my plotting stuff to be very much separate from my wrangling stuff. Also, you can name your group which feels like the easiest method to solve your problem [although you do loose the original column name]. So one method of solving what you're trying to do can be via;

library(tidyverse)

concern1_data <- function(df, col) {
  group <- enquo(col)
  df %>% 
    group_by(group = !!group) %>% 
    summarise(n = n())
}

concern2_plotting <- function(df){
  ggplot(data=df) +
    geom_bar(aes(group, n), stat = "identity")
}

mtcars %>% 
  concern1_data(am) %>% 
  concern2_plotting()

This achieves what you're trying to do more or less and keeps concerns apart (which deserves a mention).

Approach 2: Accept and Wait

Thing is: tidyeval is not yet implemented in ggplot2. - Colin Fay from link

I think this is support that is currently not in ggplot2 but I can't imagine that ggplot2 won't get this functionality. It's just not there yet.