Search code examples
rtidyeval

R how to wrap a function that uses tidyeval?


I have a function that uses tidyeval like select_this defined below. I have another function wrapper_select_this wrapping it, but I get the below error. Is there a simple way to adjust the wrapper_select_this to work (in this case: output the same as function select_this)?

library(tidyverse)

z <- c("a", "b")
df <- data.frame(Z = 1:3, a = 1:3, b = 1:3)

select_this <- function(df, x){
  x_upper <- enexpr(x) %>% str_to_upper
  
  df %>%
    select(
      all_of(x_upper), all_of(x)
    )
}

wrapper_select_this <- function(df, x){
  df %>% select_this(x)
  
}

df %>% select_this(z)
#>   Z a b
#> 1 1 1 1
#> 2 2 2 2
#> 3 3 3 3

df %>% wrapper_select_this(z)
#> Error: Can't subset columns that don't exist.
#> x Column `X` doesn't exist.

Created on 2022-04-07 by the reprex package (v2.0.1)


Solution

  • If you change select_this() to support quosures, you can then use {{ to interface with it. In this case you can use as_name() to transform a potentially quosured symbol to a string:

    z <- c("a", "b")
    df <- data.frame(Z = 1:3, a = 1:3, b = 1:3)
    
    select_this <- function(df, x) {
      x_upper <- toupper(rlang::as_name(enquo(x)))
    
      df %>%
        select(all_of(x_upper), all_of(x))
    }
    
    df %>% select_this(z)
    #>   Z a b
    #> 1 1 1 1
    #> 2 2 2 2
    #> 3 3 3 3
    

    Then use {{ to interface with it:

    wrapper_select_this <- function(df, x){
      df %>% select_this({{ x }})
    }
    
    df %>% wrapper_select_this(z)
    #>   Z a b
    #> 1 1 1 1
    #> 2 2 2 2
    #> 3 3 3 3
    

    I have to say I find it a bit confusing that you're selecting columns both by defused name and by the column names contained in the env-var of the same name.