More on Macros in R

Recently ran into something interesting in the R macros/quasi-quotation/substitution/syntax front:

D0FD431X0AI4pM8

It appears !! is no longer the last word in substitution (it certainly wasn’t the first).

The described effect is actually already pretty easy to achieve in R.

suppressPackageStartupMessages(library("dplyr"))

group_by <- wrapr::bquote_function(group_by)
summarize <- wrapr::bquote_function(summarize)

my_average <- function(data, grp_var, avg_var) {
  data %>%
    group_by(.( grp_var )) %>%
    summarize(avg = mean(.( avg_var ), na.rm = TRUE))
}

data <- data.frame(x = 1:10, g = rep(c(0,1), 5))

my_average(data, as.name("g"), as.name("x"))

## # A tibble: 2 x 2
##       g   avg
##   <dbl> <dbl>
## 1     0     5
## 2     1     6

Or if you don’t want to perform the quoting by hand.

my_average <- function(data, grp_var, avg_var,
                       grp_var_name = substitute(grp_var),
                       avg_var_name = substitute(avg_var)
                       ) {
  data %>%
    group_by(.( grp_var_name )) %>%
    summarize(avg = mean(.( avg_var_name ), na.rm = TRUE))
}

my_average(data, g, x)

## # A tibble: 2 x 2
##       g   avg
##   <dbl> <dbl>
## 1     0     5
## 2     1     6

And we can use the same Thomas Lumley / bquote() notation for string interpolation.

group_var <- as.name("g")
avg_var <- as.name("x")

wrapr::sinterp("group_var was .(group_var), and avg_var was .(avg_var)")

# [1] "group_var was g, and avg_var was x"

The .() notation has a great history in R and has been used by data.table for years.

Tags: