Home > Software engineering >  Accessing an NSE in two function-levels in R
Accessing an NSE in two function-levels in R

Time:11-09

I'm passing a column-name to one function. I want to reference in the function AND in another it calls.

This works as I expected

library(dplyr)
updown <- function(df, columnName){
    COL <- enquo(columnName)
  df %>% 
    mutate(UP = toupper(!!COL),
           DOWN = tolower(!!COL))
  }

updown(band_members, columnName = band)

# A tibble: 3 x 4
  name  band    UP      DOWN   
  <chr> <chr>   <chr>   <chr>  
1 Mick  Stones  STONES  stones 
2 John  Beatles BEATLES beatles
3 Paul  Beatles BEATLES beatles

I put the second mutate into a second function call

updown2 <- function(df, columnName){
  COL <- enquo(columnName)
  df %>% 
    mutate(UP = toupper(!!COL)) %>% 
  updown3(columnName = columnName)
}

updown3 <- function(df, columnName){
  COL <- enquo(columnName)
  df %>% 
    mutate(DOWN = tolower(!!COL))
}

updown2(band_members, columnName = band)

But got the error


Error in `h()`:
! Problem with `mutate()` input `DOWN`.
✖ object 'band' not found
ℹ Input `DOWN` is `tolower(columnName)`.
Run `rlang::last_error()` to see where the error occurred.

How should I access (via enquo) the NSE columnName in updown2, then pass it from updown2 to updown3?

CodePudding user response:

The {{ }} "curly curly" or "embrace" function works nicely here.

updown2 <- function(df, columnName){
  df %>% 
    mutate(UP = toupper( {{columnName}} )) %>% 
    updown3( {{columnName}} )
}

updown3 <- function(df, columnName){
  df %>% 
    mutate(DOWN = tolower( {{columnName}} ))
}

updown2(band_members, columnName = band)

Result

# A tibble: 3 × 4
  name  band    UP      DOWN   
  <chr> <chr>   <chr>   <chr>  
1 Mick  Stones  STONES  stones 
2 John  Beatles BEATLES beatles
3 Paul  Beatles BEATLES beatles

CodePudding user response:

You need to use your unquoted COL when you call updown3():

library(dplyr)

updown2 <- function(df, columnName){
  COL <- enquo(columnName)
  df %>% 
    mutate(UP = toupper(!!COL)) %>% 
  updown3(columnName = !!COL)
}

updown3 <- function(df, columnName){
  COL <- enquo(columnName)
  df %>% 
    mutate(DOWN = tolower(!!COL))
}

updown2(band_members, columnName = band)
# A tibble: 3 × 4
  name  band    UP      DOWN   
  <chr> <chr>   <chr>   <chr>  
1 Mick  Stones  STONES  stones 
2 John  Beatles BEATLES beatles
3 Paul  Beatles BEATLES beatles

As in @JonSpring’s answer, you could use the {{ operator. {{x}} is equivalent to !!enquo(x).

  • Related