2

This comes from a different question I asked recently. As I understand curly curly {{}} from rlang is used within functions and with unquoted variables so the following function and call works:

library(ggplot2)
library(tidyverse)
library(cowplot)
library(gridExtra)

#plot function
plot_f <- function(df, x_var, y_var) {
  ggplot(df, aes(x = {{x_var}}, y = {{y_var}})) + geom_boxplot(aes(fill = {{x_var}})) +
    theme_cowplot() 
}

#pass unquoted variable
plot_f(diamonds, cut, depth)  #plots fine

enter image description here

My question is why does the following not work when I unquote the variables I want to cycle through?

#variables to cycle through
vars1 <- c("cut", "color", "clarity")

#unquoted variables
vars <- noquote(vars1)
vars
#[1] cut     color   clarity

plot_list <- vars %>% 
  map(., ~plot_f(diamonds, .x, depth))

#plots but fill isn't correct
grid.arrange(grobs = plot_list, ncol = 1)

enter image description here

(The output should be three different plots, with the first one looking like the plot from the first example.)

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
user63230
  • 4,095
  • 21
  • 43
  • see [this](https://stackoverflow.com/questions/55132771/standard-eval-with-ggplot2-without-aes-string) and [this](https://stackoverflow.com/questions/15323269/addressing-x-and-y-in-aes-by-variable-number/54755181#54755181) – IceCreamToucan Dec 02 '19 at 17:58
  • @IceCreamToucan thanks but those examples are trying to pass quoted variables, I'm trying to do the opposite using curly curly i.e. pass unquoted variables, I thought this was possible with the latest release of `ggplot` as explained [here](https://ggplot2.tidyverse.org/dev/articles/ggplot2-in-packages.html#using-aes-and-vars-in-a-package-function) "If the column name or expression is supplied by the user, you can also pass it to aes() or vars() using {{ col }}" – user63230 Dec 02 '19 at 18:57
  • 1
    Maybe you could give an example of your actual input? If you really have input of class `noquote` (like the `vars` object), you can use `as.character` to convert to character so that the linked solutions will work/apply. Honestly though, I think it's unlikely your input is actually a `noquote` class object. It seems you're just misunderstanding what "unquoted" means in this context. All `noquote` does is change the way the character object looks when printed, so that there are no quotes around the elements. This kind of "quoting" is not the same as "quoting" in the tidyeval context. – IceCreamToucan Dec 02 '19 at 19:07
  • ah i get you, I was just thinking was there way to use curly curly in a function (instead of `.data[[col]]`) and pass it a vector/list into `map/lapply` (so really turn the vector into something else first - using `as.character` as you suggest is probably what I'm after) as opposed to only passing in one variable like I did in my working example. – user63230 Dec 02 '19 at 19:35

1 Answers1

2

Nonstandard evaluation is tricky. The key here is that you need a list of symbols, not a character vector, and then you also need to use the bang-bang operator (!!) in your map() call because you want to capture the value of .x, not .x itself.

library(tidyverse)
library(cowplot)
library(gridExtra)
library(rlang)

#plot function
plot_f <- function(df, x_var, y_var) {
  ggplot(df, aes(x = {{x_var}}, y = {{y_var}})) + geom_boxplot(aes(fill = {{x_var}})) +
    theme_cowplot() 
}

#variables to cycle through
vars1 <- c("cut", "color", "clarity")
# convert to symbols
vars <- syms(vars1)

# note the !! in front of .x
plot_list <- vars %>% 
  map(., ~plot_f(diamonds, !!.x, depth))

grid.arrange(grobs = plot_list, ncol = 1)

Note that noquote() outputs a character string (just of class 'noquote'), but you need a list of symbols.

vars <- noquote(vars1)
str(vars)
#>  'noquote' chr [1:3] "cut" "color" "clarity"

vars <- syms(vars1)
str(vars)
#> List of 3
#>  $ : symbol cut
#>  $ : symbol color
#>  $ : symbol clarity
Claus Wilke
  • 16,992
  • 7
  • 53
  • 104