lalalallala
lalalallala

Reputation: 13

How do I make my custom function return an error message if one of the vector elements has NA or is not an integer in R?

What I want to do is a function where x is a vector, and y any integer. If y is inside the vector x, then it should return "TRUE". Also, if the vector contains NAs or decimals, then it should print an error message.

So far I have created this, but if I input search(c(9,8,3,NA),3) it gives me this message:

Warning message:
In if (x%%1 != 0 | anyNA(x) == TRUE) { :
  the condition has length > 1 and only the first element will be used

If if input a vector with a decimal in it like this search(c(8,9,7.01,12),12)it won't give an ERROR message.

This is my code so far:

search <- function(x,y){
  if (x%%1!=0 | anyNA(x)==TRUE){
    print("ERROR")
  }else{
    if(y %in% x){
      print(TRUE)
    }
    else
      print(FALSE)
  }
}

Upvotes: 1

Views: 2130

Answers (2)

Len Greski
Len Greski

Reputation: 10865

Use sum(x %% 1) > 0 to validate x.

search <- function(x,y){
     if (sum(x %% 1) | anyNA(x)==TRUE){
          stop("ERROR")
     }else{
          if(y %in% x){
               print(TRUE)
          }
          else
               print(FALSE)
     }
}

...and the output:

> search(c(9,8,3,NA),3)
Error in search(c(9, 8, 3, NA), 3) : ERROR

> search(c(9,8,3),3)
[1] TRUE
>
> search(c(9,8,3),13)
[1] FALSE
> 

Also, it's good practice to use the stop() function to communicate an error within an R function. stop() stops execution of the current expression and executes an error action.

Upvotes: 0

Allan Cameron
Allan Cameron

Reputation: 174448

If you want your function to produce an error, use stop, not print. Any program that relies on the output of the function will otherwise keep running, without noticing anything is wrong. This could make things very hard to debug later. stop throws an error, which can then be handled appropriately. Also, because the function will exit if the condition is met, you don't need an else afterwards: that code will only ever run if the condition isn't met, so the else is redundant.

You can also simplify some of the logic. You don't need if(condition == TRUE), since if(condition) does the same thing. Finally, the construction if(condition){ print(TRUE) } else { print(FALSE) } is logically identical to print(condition)

search <- function(x, y){
  if (any(x %% 1 != 0) | anyNA(x) | length(y) != 1) stop("Error")
  y %in% x
}

Now try it on test cases:

search(c(1, 3, 5), 3)
#> [1] TRUE
search(c(1, 3, 5), 2)
#> [1] FALSE
search(c(1, 3, NA), 3)
#> Error in search(c(1, 3, NA), 3): Error
search(c(1, 3, 5.1), 3)
#> Error in search(c(1, 3, 5.1), 3): Error
search(c(1, 3, 5), c(1, 3))
#> Error in search(c(1, 3, 5), c(1, 3)): Error

Created on 2020-05-15 by the reprex package (v0.3.0)

Upvotes: 1

Related Questions