Baraliuh
Baraliuh

Reputation: 2141

Check if a tidyselect is NULL and if so, set a default tidyselect method

I am struggling to set a default selection method if NULL is given. For example, let's say I want to implement a function that squares all values for some tidyselect method, symbol, or string, and if none is given, then by default it squares all numeric values. Here is a repex with the cases I am trying to get working:

#Load package
suppressMessages(library(dplyr))
#Define function
square_columns <- function(data, target = NULL){
  if (is.null(target)){
    target <- rlang::expr(where(is.numeric))
  }
  data %>% 
    dplyr::mutate(
      dplyr::across(!!target, magrittr::raise_to_power, 2)
    )
}
# Examples
# Works
iris %>% 
  square_columns(target = 'Sepal.Length') %>% 
  invisible()
# Works
iris %>% 
  square_columns(target = c('Sepal.Length', 'Sepal.Width')) %>% 
  invisible()
# Works
iris %>% 
  square_columns() %>% 
  invisible()
# Fails
iris %>% 
  square_columns(target = contains('Sepal'))
#> Error: `contains()` must be used within a *selecting* function.
#> i See <https://tidyselect.r-lib.org/reference/faq-selection-context.html>.
# Fails
iris %>% 
  square_columns(target = Sepal.Length)
#> Error in square_columns(., target = Sepal.Length): object 'Sepal.Length' not found

Created on 2021-06-16 by the reprex package (v2.0.0)

Upvotes: 4

Views: 318

Answers (1)

MrFlick
MrFlick

Reputation: 206253

You need to be a bit more careful about when target actually gets evaualted. This should work

square_columns <- function(data, target = NULL){
  target <- enquo(target)
  if (rlang::quo_is_null(target)){
    target <- rlang::expr(where(is.numeric))
  }
  data %>% 
    dplyr::mutate(
      dplyr::across(!!target, magrittr::raise_to_power, 2)
    )
}

When you run is.null(target), you are evaluating that parameter and you can't evaluate something that uses contains() outside the context of a data.frame. So it's better to explicitly create a quosure from the parameter and use the safer rlang::quo_is_null to check for NULL values.

Upvotes: 7

Related Questions