如何向使用 tidy eval 框架创建的函数添加检查?

How do I add checks to a function created using tidy eval framework?

假设我使用 tidy eval 框架创建了一个函数 -

library(tidyverse)
library(rlang)

my_function <- function(data, var){
    
    var_expr <- enquo(var)
    
    data %>% 
        group_by(!!var_expr) %>% 
        summarise(count = n()) %>% 
        ungroup()
}

当我运行以下函数时,我得到下面的结果

my_function(mtcars, cyl)

# A tibble: 3 x 2
    cyl count
  <dbl> <int>
1     4    11
2     6     7
3     8    14

如何向该函数添加以下检查 -

  1. 检查 data 是否是数据帧。如果不是,return错误data should be a dataframe
  2. 检查 var 是否丢失。如果是 return 错误 var is missing

您可以进行如下修改。

  • 为了检查我们的输入数据是否属于特定的 class 我们可以检查它的 class 属性,在这种情况下无论是数据框还是 tibble 它们都包含 class data.frame
  • 还有missing函数,它通常在很多函数内部使用来检查参数是否被赋值,以便它们生成一个值作为默认值。在你的情况下,我们可以终止函数的执行(你也可以检查 length 函数的源代码,了解它如何在 size 参数丢失时指定一个值)
  • 您可以使用 base::stop 代替亲爱的@akrun
  • 指定的 rlang::abort
library(rlang)

my_function <- function(data, var){
  if(!"data.frame" %in% attr(data, "class")) {
    abort("data should be a data frame")
  } 
  if(missing(var)) {
    abort("var is missing")
  }
  
  var_expr <- enquo(var)
  
  data %>% 
    group_by(!!var_expr) %>% 
    summarise(count = n()) %>% 
    ungroup()
}

特别感谢 亲爱的 @27 ϕ 9 让我注意到这个宝贵的观点。我们还可以在 stopifnot 函数中自定义输出错误消息,这是检查输入参数的另一种方式:

my_function <- function(data, var){
  stopifnot("The input data is not of class data frame" = "data.frame" %in% attr(data, "class") ,
            "var is missing" = !missing(var)) 
  
  var_expr <- enquo(var)
  
  data %>% 
    group_by(!!var_expr) %>% 
    summarise(count = n()) %>% 
    ungroup()
}

特别感谢 亲爱的 @IceCreamToucan 提出了另一个选项,它使用 inherits 函数代替 attr。如果输入数据在其 class 属性中不包含 data.frame 它 returns FALSE:

my_function <- function(data, var){
  if(!inherits(data, "data.frame")) {
    stop("data is not of class data.frame")
  } 
  
  if(missing(var)) {
    stop("var is missing")
  }
  
  var_expr <- enquo(var)
  
  data %>% 
    group_by(!!var_expr) %>% 
    summarise(count = n()) %>% 
    ungroup()
}