检查 tidyselect 是否为 NULL,如果是,则设置默认的 tidyselect 方法

问题描述

如果给定 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 package (v2.0.0) 于 2021 年 6 月 16 日创建

解决方法

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) 时,您正在评估该参数,并且您无法评估在 data.frame 上下文之外使用 contains() 的内容。所以最好从参数中显式创建一个 quosure 并使用更安全的 rlang::quo_is_null 来检查 NULL 值。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...