【问题标题】:How do I add checks to a function created using tidy eval framework?如何向使用 tidy eval 框架创建的函数添加检查?
【发布时间】:2021-07-19 21:02:51
【问题描述】:

假设我使用 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 是否为数据框。如果不是,返回错误data should be a dataframe
  2. 检查var 是否丢失。如果是这样返回错误var is missing

【问题讨论】:

    标签: r tidyeval


    【解决方案1】:

    您可以进行以下修改。

    • 为了检查我们的输入数据是否属于特定类,我们可以检查其类属性,在这种情况下,无论是数据框还是小标题,它们都包含类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 的选项。如果输入数据在其类属性中不包含data.frame,则返回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()
    }
    

    【讨论】:

    • 或在base Rstop 中代替rlang::abort
    • 完全掌握。我看到 OP 使用了rlang,所以我继续使用它。更不用说我真的很喜欢rlang
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 2020-10-23
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    相关资源
    最近更新 更多