I know you can use "indirection" when you use dplyr::select()
inside a function:
myselect1 <- function( df, select_arg ) {
df %>%
select( {{ select_arg }} )
}
starwars %>%
myselect1( contains( '_color' ) ) %>%
head( n = 3 )
# hair_color skin_color eye_color
# <chr> <chr> <chr>
# blond fair blue
# NA gold yellow
# NA white, blue red
But, since you can only use a selection helper within a selecting function, if I want to make the selection conditional, I get an error:
myselect2 <- function( df, select_arg = NULL ) {
if( !is.null( select_arg ) ) {
df %>%
select( {{ select_arg }} )
} else {
df
}
}
starwars %>%
myselect2( contains( '_color' ) ) %>%
head( n = 3 )
# Error:
# ! `contains()` must be used within a *selecting* function.
# i See <https://tidyselect.r-lib.org/reference/faq-selection-context.html>.
# Backtrace:
# 1. starwars %>% myselect2(contains("_color")) %>% head(n = 3)
# 4. tidyselect::contains("_color")
# 6. tidyselect::peek_vars(fn = "contains")
How could I test whether the selection helper exists or not?
You have to rlang::enquo
te the function argument. Afterwards you could check for NULL
using rlang::quo_is_null
:
library(dplyr, warn=FALSE)
myselect2 <- function(df, select_arg = NULL) {
if (!rlang::quo_is_null(enquo(select_arg))) {
df %>%
select({{ select_arg }})
} else {
df
}
}
starwars %>%
myselect2(contains("_color")) %>%
head(n = 3)
#> # A tibble: 3 × 3
#> hair_color skin_color eye_color
#> <chr> <chr> <chr>
#> 1 blond fair blue
#> 2 <NA> gold yellow
#> 3 <NA> white, blue red
starwars %>%
myselect2() %>%
head(n = 3)
#> # A tibble: 3 × 14
#> name height mass hair_…¹ skin_…² eye_c…³ birth…⁴ sex gender homew…⁵
#> <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr> <chr>
#> 1 Luke Skywal… 172 77 blond fair blue 19 male mascu… Tatooi…
#> 2 C-3PO 167 75 <NA> gold yellow 112 none mascu… Tatooi…
#> 3 R2-D2 96 32 <NA> white,… red 33 none mascu… Naboo
#> # … with 4 more variables: species <chr>, films <list>, vehicles <list>,
#> # starships <list>, and abbreviated variable names ¹hair_color, ²skin_color,
#> # ³eye_color, ⁴birth_year, ⁵homeworld