Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

r

tidyeval

Say I have created a function using the tidy eval framework -

library(tidyverse)
library(rlang)

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

When I run the following function, I get the result below it

my_function(mtcars, cyl)

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

How do I add the following checks to this function -

  1. Check if data is a dataframe. If not, return the error data should be a dataframe
  2. Check if var is missing. If so return the error var is missing
like image 376
The Rookie Avatar asked Apr 30 '26 02:04

The Rookie


1 Answers

You can make the following modifications.

  • In order to check if our input data is of a particular class we can check its class attribute and in this case whether it's a data frame or tibble they both contains the class data.frame
  • Also for missing function, it is normally used inside many functions to check whether an argument is assigned a value so that they generate a value as the default value. In your case we can terminate the execution of the function (you can also check the source code of length function on how it specifies a value for size argument when it is missing)
  • You can use base::stop in place of rlang::abort as specified by dear @akrun
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()
}

Special thanks to dear @27 ϕ 9 for bringing this valuable point to my attention. We can also customize the output error message in stopifnot function which is another way of checking your input arguments:

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

Special thanks to dear @IceCreamToucan for presenting yet another option which is using the inherits function in lieu of attr. In case the input data does not include data.frame in its class attributes it 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()
}
like image 165
Anoushiravan R Avatar answered May 01 '26 21:05

Anoushiravan R