Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suppress warnings using tryCatch in R

What I'm trying to do

Write a tryCatch that will handle an error value but will ignore a warning. As an example

foo <- function(x) {
  if (x == 1) {
    warning('Warning')
  } else if (x == 0) {
    stop('Error')
  }
  return(1)
}

bar <- function(x){
  tryCatch(
    expr    = foo(x),
    error   = identity,
    warning = function(w) invokeRestart("muffleWarning")
  )
}

So foo warns you if you pass a 0, and errors if you pass a 1. The intent of bar is that you get an error if you pass a 0, but it suppresses the warning generated by bar if you pass a 1. The invokeRestart("muffleWarning") command comes from the definition of suppressWarnings. It does not work in the construction I have here and I do not know why. (Ironically it generates an error, so trying that successfully escalated a warning I didn't want into an error that I can't interpret.)

The Dumb Answer (TM) I don't want to use and why

This definition of bar will work

bar <- function(x){
  tryCatch(
    expr    = foo(x),
    error   = SomeFunctionThatDoesNotMatter,
    warning = function(w){suppressWarnings(foo(x))}
  )
}

bar does exactly what I want it to, but it does it in a potentially terrible way. Imagine that instead of expr = foo(x) as I have here, that I have expr = lapply(X=1:50, ...) and that the FUN takes an hour to run. If X[50] generates the only warning then my run time has double from 50 hours to 100 hours (yuck).

The Questions

  1. Why does invokeRestart("muffleWarning") not work in my example above?
  2. When using tryCatch, what function should be assigned to warning in order to allow the code to simply keep running and suppress the warnings that are generated?

Thanks for reading!

like image 227
Adam Hoelscher Avatar asked Mar 03 '16 23:03

Adam Hoelscher


1 Answers

I ran into this problem after following nrussell's intuition. The solution is to replace the generic

tryCatch({
  some_fn()
}, warning = function(w) {
  print(paste('warning:', w))
}, error = function(e) {
  print(paste('error:', e))
})

with

tryCatch({
  some_fn()
}, error = function(e) {
  print(paste('error:', e))
})

This format/syntax has worked for me. You could easily enclose it in a function like you need to

like image 54
3pitt Avatar answered Oct 16 '22 01:10

3pitt