Search code examples
rtidyverse

How to stop R from executing when value is non-numeric


Everything works in this function except when I am trying to stop the code from running if the user tries to enter non-numerical data. Could someone point out what am I doing wrong?

#DATA
library(tidyverse)
x <-  structure(list(wk = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 
2, 3, 3, 3, 3, 3, 3), month = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1), xd = c(0.0370098838217444, 0.0391215970961887, 
0.0409865246890313, NA, NA, NA, NA, 0.015188, 0.007513, 0.012716, 
0.013962, 0.014259, 0.023553, 0.032122, 0.03953, 0.028946, 0.030769, 
0.030815, 0.029187, 0.022604), td = c(0.02701157274146, 0.0284158620689655, 
0.0296560389182058, NA, NA, NA, NA, 0.0125, 0.007396, 0.010856, 
0.011685, 0.011882, 0.018063, 0.023761, 0.028687, 0.021649, 0.022861, 
0.022892, 0.021809, 0.017432), pd = c(317.308439683869, 0, 126.719553152898, 
NA, NA, NA, NA, 2671.6, 3540.6976744186, 1270.35740604274, 1067.69362430466, 
688.099646524154, 317.444499806234, 420.941879550524, 280.475476696762, 
250.681324772507, 159.048160622895, 258.125109208457, 450.868907331836, 
0), year = c(2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 
2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 
2007)), class = "data.frame", row.names = c(NA, -20L))

x$test <- rep("hi",nrow(x))   #To test the function by entering text instead of numbers
x

#WORKS AS EXPECTED
ci_boot <- function(dat, by, var, conf.int = 0.90,...) {
  dat %>%
    group_by({{by}}) %>%   
    dplyr::summarise(mean=list(smean.cl.boot({{var}}, conf.int=conf.int))) %>%
    unnest_wider(mean)
}
ci_boot(dat = x, by = wk, var = pd)

#BUT THIS DOESN'T WORK WHEN I ADD THE stop() FUNCTION TO CHECK FOR IF VALUES ARE NUMERIC
ci_boot <- function(dat, by, var, conf.int = 0.90,...) {
  if(!is.numeric(var)) {stop("'var' must be numeric")}  #Tried {{ }} around 'var' as well
  dat %>%
    group_by({{by}}) %>%   
    dplyr::summarise(mean=list(smean.cl.boot({{var}}, conf.int=conf.int))) %>%
    unnest_wider(mean)
}
ci_boot(dat = x, by = wk, var = pd)

Error in ci_boot(dat = x, by = wk, var = pd) : object 'pd' not found

Solution

  • The problem is that pd exists in the dat frame, not in the .GlobalEnv nor in the function's environment. You must first get pd in the evaluation frame where it exists. In the code below this is done with pull/{{.

    library(tidyverse)
    
    ci_boot <- function(dat, by, var, conf.int = 0.90,...) {
      v <- pull(dat, {{var}})
      if(!is.numeric(v)) {stop("'var' must be numeric")}  #Tried {{ }} around 'var' as well
      dat %>%
        group_by({{by}}) %>%   
        dplyr::summarise(mean=list(Hmisc::smean.cl.boot({{var}}, conf.int=conf.int))) %>%
        unnest_wider(mean)
    }
    ci_boot(dat = x, by = wk, var = pd)
    #> # A tibble: 3 × 4
    #>      wk  Mean Lower Upper
    #>   <dbl> <dbl> <dbl> <dbl>
    #> 1     1  148.  42.2  254.
    #> 2     2 1425. 750.  2198.
    #> 3     3  233. 139.   329.
    
    x$test <- rep("hi",nrow(x))
    ci_boot(dat = x, by = wk, var = test)
    #> Error in ci_boot(dat = x, by = wk, var = test): 'var' must be numeric
    

    Created on 2024-09-26 with reprex v2.1.0