Search code examples
rdplyrnsenon-standard-evaluation

Accessing an NSE in two function-levels in R


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?


Solution

  • 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).