Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Escape overscoping in the tidyeval framework

If I want to make overscoping explicit, I can use the .data pronoun like this

library(dplyr)

cyl <- 3
transmute(as_tibble(mtcars), cyl_plus_one = .data$cyl + 1)
#> # A tibble: 32 x 1
#>    cyl_plus_one
#>           <dbl>
#>  1            7
#>  2            7
#>  3            5
#>  4            7
#>  5            9
#>  6            7
#>  7            9
#>  8            5
#>  9            5
#> 10            7
#> # ... with 22 more rows

However, what about the opposite, i.e. if I want to avoid overscoping explicitly? In the example below, I would like to add a new column that contains the value b (supplied via the function call, not the b in the data) plus 1, which does obviously not work the way it's stated now (because of overscoping).

library(dplyr)
add_one <- function(data, b) {
  data %>%
    mutate(a = b + 1)
}
data <- data_frame(
  b  = 999
)
add_one(data, 3)
#> # A tibble: 1 x 2
#>       b     a
#>   <dbl> <dbl>
#> 1   999  1000

I also tried to create the new value outside the mutate() call, but then I still need to rely on new_val being not in the data.

library(dplyr)
add_one <- function(data, b) {
  new_val <- b + 1
  data %>%
    mutate(a = new_val)
}
like image 721
Lorenz Walthert Avatar asked Jan 12 '18 18:01

Lorenz Walthert


1 Answers

Just unquote with !! to look for a variable with that name above the data frame scope:

library(tidyverse)

add_one <- function(data, b) {
    data %>% mutate(a = !!b + 1)
}

data <- data_frame(b  = 999)

add_one(data, 3)
#> # A tibble: 1 x 2
#>       b     a
#>   <dbl> <dbl>
#> 1   999  4.00
like image 88
alistaire Avatar answered Sep 23 '22 01:09

alistaire