2

如果给出 NULL,我正在努力设置默认选择方法。例如,假设我想实现一个函数,对某个 tidyselect 方法、符号或字符串的所有值进行平方,如果没有给出,则默认情况下它对所有数值进行平方。这是我试图开始工作的案例的代表:

#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

reprex 包于 2021-06-16 创建 (v2.0.0 )

4

1 回答 1

4

您需要更加小心何时target实际被评估。这应该工作

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)
    )
}

运行时is.null(target),您正在评估该参数,并且无法评估contains()在 data.frame 上下文之外使用的内容。因此,最好从参数显式创建一个 quosure 并使用更安全rlang::quo_is_null的方法来检查 NULL 值。

于 2021-06-16T18:03:18.137 回答