3

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!

Edwin
  • 3,184
  • 1
  • 23
  • 25
  • If it is a string, you need `aes_string`, What is the issue with that one? – akrun Jul 24 '17 at 11:21
  • It feels like a big detour, quoting, then using quo_text, then using aes_string. Hoped there was a more straightforward solution. – Edwin Jul 24 '17 at 11:33
  • Yet, this [seems to be the way to go](http://colinfay.me/tidyeval-1/) when using tidyeval. – lukeA Jul 24 '17 at 11:51

2 Answers2

3

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)
Stanwood
  • 268
  • 1
  • 10
2

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.

cantdutchthis
  • 31,949
  • 17
  • 74
  • 114
  • I found out that indeed the tidyeval will be coming to ggplot soon. I like your two step approach, only drawback in this example is that you loose the column name on the plot, but that is of course easily fixed. – Edwin Jul 28 '17 at 09:52