0
id <- 1:30
x<-rnorm(30,1,10)
y<-rnorm(30,1,10)

data<-data.frame(id,x,y)

add<-function(data,
              y_1,
              y_2){
  
 
 
    data<-dplyr::mutate(data,
           higher_one = dplyr::case_when(
      {{y_1}} > {{y_2}} ~ "1",
      {{y_1}} < {{y_2}} ~ "2",
      {{y_1}} == {{y_2}} ~ "equal"
    ))
}

data2<-add(data,x,y)

so, suggestions from my collaborator are:

  1. remove the curly double brace because it is a tidy evaluation. and use standard evaluation instead

however, if I remove that curly double brace, the function does not work at all.

with the curly double brace, it works. but my collaborator does not want this, so I want to make my function without curly double brace, but equivocal to current function

Tube
  • 177
  • 5
  • 1
    Could you describe what you are trying to do, and articulate your question a bit more clearly? – jpsmith Apr 22 '23 at 14:28
  • 1
    … could you ask your collaborator for clarification?! This is literally what tidy evaluation (and in particular the `{{…}}` syntax) is *for*. And the current code works, doesn’t it? – Konrad Rudolph Apr 22 '23 at 14:57

2 Answers2

2

There are many ways to accomplish the same without relying on tidy evaluation. What works best depends on your data. The easiest way, starting from your code, is perhaps to pass the data directly as vectors, as per the add_new function proposed below.

library(dplyr, warn.conflicts = FALSE)
id <- 1:30
x<-rnorm(30,1,10)
y<-rnorm(30,1,10)

data<-data.frame(id,x,y)

add<-function(data,
              y_1,
              y_2){
  
  data<-dplyr::mutate(data,
                      higher_one = dplyr::case_when(
                        {{y_1}} > {{y_2}} ~ "1",
                        {{y_1}} < {{y_2}} ~ "2",
                        {{y_1}} == {{y_2}} ~ "equal"
                      ))
}

data2<-add(data,x,y)

add_new <- function(id,
                    y_1, 
                    y_2) {
  data.frame(
    id = id, 
    x = y_1, 
    y = y_2
  ) %>% 
    dplyr::mutate(
      higher_one = 
        dplyr::case_when(
          y_1 > y_2 ~ "1",
          y_1 < y_2 ~ "2",
          y_1 == y_2 ~ "equal"
        ))
}

add_new(id, x, y)
#>    id           x           y higher_one
#> 1   1  -0.1230021  11.7864472          2
#> 2   2  -8.1725977   3.7887923          2
#> 3   3 -12.6658752 -14.1905973          1
#> 4   4  -3.1449900   2.7285435          2
#> 5   5 -15.9884739  -5.0641743          2
#> 6   6   4.9679469   3.3170440          1
#> 7   7   3.8275793   5.7313615          2
#> 8   8  -1.0790800  13.6493031          2
#> 9   9  11.0294920 -15.6026409          1
#> 10 10   4.4074939   5.0595880          2
#> 11 11  11.3505836  24.9155916          2
#> 12 12 -10.5816808   7.5058363          2
#> 13 13   1.1865215   3.8281185          2
#> 14 14  14.8343362   2.2092123          1
#> 15 15  11.0189092  -7.0201287          1
#> 16 16  -8.4163492   2.8795916          2
#> 17 17  -2.4046220 -10.3922635          1
#> 18 18   4.2246253  -4.2568981          1
#> 19 19  18.5017614 -10.1585758          1
#> 20 20  -6.6245076 -16.3040852          1
#> 21 21   2.2332512   0.2707015          1
#> 22 22   0.6737131   6.1809546          2
#> 23 23  20.1771217 -13.0768923          1
#> 24 24  10.2781681  -0.5965996          1
#> 25 25  -0.2431778  -7.7948312          1
#> 26 26  -5.0216330   9.8321536          2
#> 27 27 -14.8153713   5.4752875          2
#> 28 28 -11.9017021 -16.8563457          1
#> 29 29   1.9697144  14.6432801          2
#> 30 30  -9.7669270  -1.9020736          2

identical(add(data,x,y),add_new(id, x, y))
#> [1] TRUE

Created on 2023-04-22 with reprex v2.0.2

giocomai
  • 3,043
  • 21
  • 24
1

Instead of interpolating with {{, subset with .data:

add <- function(data, y_1, y_2) {
  dplyr::mutate(
    data,
    higher_one = dplyr::case_when(
      .data[[y_1]] > .data[[y_2]] ~ "1",
      .data[[y_1]] < .data[[y_2]] ~ "2",
      .data[[y_1]] == .data[[y_2]] ~ "equal"
    )
  )
}

data2 <- add(data, "x", "y")
Lionel Henry
  • 6,652
  • 27
  • 33
  • what does . mean in this context? – Tube Apr 22 '23 at 16:18
  • 1
    It means that `.data` is a special variable in the tidyeval context. `.data` is a bit like the magrittr pronoun `.`, but it's tidyeval-aware, so for instance in a grouped data frame it represents the current group slice rather than the whole data frame. – Lionel Henry Apr 22 '23 at 23:15
  • Thanks! does it mean that .data is not standard evaluation? (is it tidy evaluation?) – Tube Apr 22 '23 at 23:57
  • 1
    `.data` creates a bridge between standard evaluation (column names as strings) and NSE/tidyeval. So if your function passes all inputs to `.data`, or to `all_of()` in tidyselect context, then your function is a pure standard eval function. – Lionel Henry Apr 23 '23 at 09:25