Search code examples
rdplyrrlang

In dplyr using quasiquotation, not seeing column name in spliced function call


Example:

library(dplyr)

df <- tibble(a = c(10, 10, 10, 20, 20),
             b = c(1, 2, 10, 2, 4))

## produces desired result:
df %>%
    group_by(a) %>%
    summarize(mn = mean(b), md = median(b))

stats <- function(x){
    list(mn = mean(x), md = median(x)) }

## object 'b' not found:
df %>%
    group_by(a) %>%
    summarize(!!! stats(b))

The call stats(b) does not see column b. What is the simplest solution that does not involve changing the stats function?

R version 3.4.3, dplyr version 0.7.2


Solution

  • !!! is meant to change the call to a function. Which means it evaluates the target in the current environment in order to change the call before running it. You seem to want to use an on object returned after a function call. But in order to use things like b in that function call, you need to delay the evaluation of b till the function is actually run. So the !!! and the use of b both need to be evaluated a different times so you run into this problem.

    This is something you still should be using do() for, see dplyr summarise() with multiple return values from a single function. For example you can do

    df %>%
      group_by(a) %>%
      do(data.frame(stats(.$b)))
    

    Or if you were to re-write the stats() function, it might look something like this

    stats <- function(x){
      x <- enquo(x)
      quos(mn = mean(!!x), md = median(!!x)) }
    
    df %>%
      group_by(a) %>%
      summarize(!!! stats(b))