8

The new curly curly method of tidy evaluation is explained in this article. Several examples are given demonstrating the use of this style of non-standard evaluation (NSE).

library(tidyverse)

# Example 1 --------------------------
max_by <- function(data, var, by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(maximum = max({{ var }}, na.rm = TRUE))
}
starwars %>% max_by(height)
starwars %>% max_by(height, by = gender)

# Example 2 --------------------------
summarise_by <- function(data, ..., by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(...)
}

starwars %>%
  summarise_by(average = mean(height, na.rm = TRUE),
               maximum = max(height, na.rm = TRUE),
               by = gender)

I created some of my own functions and this is indeed a lot easier framework to develop in, instead of worrying about all the quosures and bangs and all of that.

However, this same article explains that we're not completely out of the woods yet:

You only need quote-and-unquote (with the plural variants enquos() and !!!) when you need to modify the inputs or their names in some way.

... and no example is provided. Not complaining, just asking if somebody can fill in the gap and provide an example. Not being fluent in Tidy evaluation, I really don't understand what the author is getting at with that quote (pardon the pun).

Display name
  • 4,153
  • 5
  • 27
  • 75
  • Suppose you want to create a column with the format `summarise(colNm :=`, you may need the !! – akrun Jul 08 '19 at 13:50
  • Your question is not specific, so it is not easier to answer – akrun Jul 08 '19 at 13:55
  • @akrun What I'm looking for are examples of _curly curly_ Tidy evaluation where I will be forced to use `enquos()` or `!!!`. Preferably I'd like to see an example of each one used individually. I wish it was in the referenced article but it's not. – Display name Jul 08 '19 at 14:04
  • The reason why I said that it is broad is because if I come up with an example, another person will come up with another instances – akrun Jul 08 '19 at 14:06
  • 1
    @akrun what I usually do is wait 24 hours and the answer that best demonstrates the concepts I'm looking for I upvote and mark solved. You've always been a great help, and I know you got frustrated before when this type of thing happens (other peoples examples and comment fights). Please don't take anything personally. Most people here are putting in good faith efforts to code better and I can only believe you are too. Thank you. – Display name Jul 08 '19 at 14:10
  • I posted that as answer because of your comment `and no example is provided. Not complaining, j` – akrun Jul 08 '19 at 14:22
  • Just deleted my post so the comments can be posted below the OP's post and not below my answer – akrun Jul 08 '19 at 16:46
  • I don't get it, your answer was legit and Jason cannot see comments of deleted answers – moodymudskipper Jul 08 '19 at 16:49

1 Answers1

7

Say you want a version of the following function that takes multiple inputs instead of just a single var:

mean_by <- function(data, var, by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(average = mean({{ var }}, na.rm = TRUE))
}

You can't just pass ... to summarise, because then the user needs to call mean() themselves.

mean_by <- function(data, var, ..., by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(...)
}

mtcars %>% mean_by(foo = disp)
#> Error: Column `foo` must be length 1 (a summary value), not 32

mtcars %>% mean_by(foo = mean(disp))
#> # A tibble: 1 x 1
#>     foo
#>   <dbl>
#> 1  231.

The solution is to quote the dots, modify each of the inputs so they are wrapped in a new call to mean(), and then splice them back:

mean_by <- function(data, ..., by) {
  # `.named` makes sure the dots have default names, if not supplied
  dots <- enquos(..., .named = TRUE)

  # Go over all inputs, and wrap them in a call
  dots <- lapply(dots, function(dot) call("mean", dot, na.rm = TRUE))

  # Finally, splice the expressions back into `summarise()`:
  data %>%
    group_by({{ by }}) %>%
    summarise(!!!dots)
}

We are considering how we could improve syntax for this case. Early thoughts at http://rpubs.com/lionel-/superstache

Lionel Henry
  • 6,652
  • 27
  • 33
  • 5
    _"This (superstache) operator would enable new patterns that are currently impossible to do without learning about metaprogramming such as quoting inputs, creating calls, etc."_ Yes. Please implement this superstache in the next version of rlang. Let metaprogramming remain "advanced" while allowing intermediate users to still be tidyeval ninjas through the use of this `{{{ }}}`. I can remember double curly and triple curly fairly easily, whereas I can hardly remember a quote from a quosure from a quoture from a bang from a bang bang ting tang walla walla bing bang. – Display name Jul 09 '19 at 21:15
  • @Lionel Any update on this after a year? I couldn't get anything new from googling "dplyr superstache" or checking the programming vignette – lost Aug 05 '20 at 01:12