3

I have the following function which works fine, but I am not sure if this is the actual way to do it as programming with tidyverse changed over the last year(s). I am especially interested in using a more consistent way of using strings on the LHS and RHS. In my example, there are three ways at the moment: !!, {{}} and !!as.name().

noga_data <- tibble(NOGA = c("01", "02", "03", "05"))

assign_noga_class <- function(mydata, noga2, noga_class) {

  mydata %>% 
    mutate(!!noga_class := ifelse(as.numeric({{ noga2 }} ) %in% c(1:3), 1, NA)) %>% 
    mutate(!!noga_class := ifelse(as.numeric({{ noga2 }}) %in% c(5:34), 2, !!as.name(noga_class)))
}
assign_noga_class(noga_data, NOGA, "NOGA_CLASS")

I thought that the bang-bang notation was outdated/superseded by something else. I like to know because I am using this as an example for a group I would like to teach about programming in R. Any hints on blogs or other web pages are also very welcome.

Cheers

Renger

arnyeinstein
  • 669
  • 1
  • 5
  • 14
  • I think `!!` is not outdated. Nevertheless, in your example you can replace `!!` and `!!as.name()` wit {{}} in all cases, and pass "NOGA_CLASS" unquoted. – Ric Dec 02 '22 at 13:49
  • `!!` is just more flexible than `{{ }}`. For this reason it will never completely replace the curly curly operations, but for most cases, as yours, the latter is enough. – TimTeaFan Dec 02 '22 at 14:01
  • https://www.brodrigues.co/blog/2019-06-20-tidy_eval_saga/ –  Dec 02 '22 at 14:02
  • THanks for all the inputs. Very helpful! – arnyeinstein Dec 02 '22 at 14:07
  • I disagree that this is a dupe of that question. OP is asking specifically about setting names on the lhs of `:=` in `mutate()`, which supports different methods than other tidyeval contexts (e.g., [name interpolation](https://rlang.r-lib.org/reference/glue-operators.html)). – zephryl Dec 02 '22 at 14:38
  • Suggest using `case_when` instead of two `ifelse` . – G. Grothendieck Dec 02 '22 at 14:44

1 Answers1

2

I don’t think !! is deprecated, but you can now use glue syntax to interpolate variable names (docs):

library(dplyr)

assign_noga_class <- function(mydata, noga2, noga_class) {
  mydata %>% 
    mutate("{noga_class}" := ifelse(as.numeric({{ noga2 }} ) %in% c(1:3), 1, NA)) %>% 
    mutate("{noga_class}" := ifelse(as.numeric({{ noga2 }}) %in% c(5:34), 2, !!as.name(noga_class)))
}

assign_noga_class(noga_data, NOGA, "NOGA_CLASS")
# A tibble: 4 × 2
  NOGA  NOGA_CLASS
  <chr>      <dbl>
1 01             1
2 02             1
3 03             1
4 05             2

This can be handy if you want to add to the passed variable name, e.g.,

assign_noga_class <- function(mydata, noga2, noga_class) {
  mydata %>% 
    mutate("{noga_class}" := ifelse(as.numeric({{ noga2 }} ) %in% c(1:3), 1, NA)) %>% 
    mutate("{noga_class}_v2" := ifelse(as.numeric({{ noga2 }}) %in% c(5:34), 2, !!as.name(noga_class)))
}

assign_noga_class(noga_data, NOGA, "NOGA_CLASS")
# A tibble: 4 × 3
  NOGA  NOGA_CLASS NOGA_CLASS_v2
  <chr>      <dbl>         <dbl>
1 01             1             1
2 02             1             1
3 03             1             1
4 05            NA             2

Finally, as @Jean-ClaudeArbaut points out, you can also use {{: e.g., mutate({{noga_class}} := ifelse(....

zephryl
  • 14,633
  • 3
  • 11
  • 30
  • 2
    you don't even need the double quotes: `mutate({{noga_class}} := ...`. –  Dec 02 '22 at 14:02
  • but it looks that I still have to use the !!as.name" – arnyeinstein Dec 02 '22 at 14:06
  • 2
    @Jean-ClaudeArbaut that’s good to know! But `"{"` is still useful if you want to modify the passed name — I added an example to my answer. – zephryl Dec 02 '22 at 14:08
  • @zephryl That's right. –  Dec 02 '22 at 14:12
  • 2
    @arnyeinstein No, you can replace `!!asname(noga_class)` with `{{noga_class}}` as well. Pass it without quotes to the function (i.e. it becomes a "magic function" whose arguments are not evaluated at once): `assign_noga_class(noga_data, NOGA, NOGA_CLASS)` –  Dec 02 '22 at 14:17
  • @arnyeinstein Well, to be extra accurate, arguments are never evaluated at once, but as soon as they are used. Here curly-curly allows reusing it symbolically in the function inside a tidy evaluation context. See [this](https://dcl-prog.stanford.edu/tidy-eval-detailed.html) for more details about how it works (curly-curly is not addressed here). –  Dec 02 '22 at 14:22
  • 2
    @Jean-ClaudeArbaut: Thanks! If you click on "Welcome" of the url, a newer version of the book appears with curly-curly explained (and no enquo, !!, etc.)... And the chapter your link shows does not appear any more. – arnyeinstein Dec 03 '22 at 10:29