10

I'm a huge fan of tryCatch(). However, until today I never really paid attention to the distinction between simple and regular warnings/errors and thus I don't really know how to handle them.

Actual question

What I'd like to know is how to tell tryCatch (see help file) that simple warnings are OK and that it should return the result of expr instead of jumping to the warning section.

Below you'll find a reproducible example


No tryCatch >> no warning

require("forecast")
y   <- ts(c(6178, 7084, 8162, 8462, 9644, 10466, 10748, 9963, 8194, 6848, 7027, 7269, 6775, 7819, 8371, 9069, 10248, 11030, 10882, 10333, 9109, 7685, 7602, 8350, 7829, 8829, 9948, 10638, 11253, 11424, 11391, 10665, 9396, 7775, 7933, 8186, 7444, 8484, 9864, 10252, 12282, 11637, 11577, 12417, 9637, 8094, 9280, 8334, 7899, 9994, 10078, 10801, 12950, 12222, 12246, 13281, 10366, 8730, 9614, 8639, 8772, 10894, 10455, 11179, 10588, 10794, 12770, 13812, 10857, 9290, 10925, 9491, 8919, 11607, 8852, 12537, 14759, 13667, 13731, 15110, 12185, 10645, 12161, 10840, 10436, 13589, 13402, 13103, 14933, 14147, 14057, 16234, 12389, 11595, 12772))
out <- forecast::auto.arima(x=y)
> out
Series: y 
ARIMA(4,1,1)                    

Coefficients:
         ar1      ar2     ar3      ar4      ma1
      0.6768  -0.2142  0.5025  -0.7125  -0.8277
s.e.  0.0749   0.0889  0.0874   0.0735   0.0485

sigma^2 estimated as 915556:  log likelihood=-780.33
AIC=1572.65   AICc=1573.62   BIC=1587.91

tryCatch >> simple warning

When I wrap it with tryCatch, it detects a simple warning that will cause my expr block to be "skipped" in favor of the warning section. Thus the function does not return the estimation result, but the simple warning.

mod <- tryCatch(
    out <- forecast::auto.arima(x=y),
    error=function(e) {
        print(e)
    },
    warning=function(w) {
        print(w)
    }
)

> mod 
<simpleWarning in kpss.test(x): p-value smaller than printed p-value>

Current workaround

if (any(class(mod) == "simpleWarning")) {
    mod <- forecast::auto.arima(x=y)
}

> mod
Series: y 
ARIMA(4,1,1)                    

Coefficients:
         ar1      ar2     ar3      ar4      ma1
      0.6768  -0.2142  0.5025  -0.7125  -0.8277
s.e.  0.0749   0.0889  0.0874   0.0735   0.0485

sigma^2 estimated as 915556:  log likelihood=-780.33
AIC=1572.65   AICc=1573.62   BIC=1587.91
Rappster
  • 12,762
  • 7
  • 71
  • 120
  • I often find it helpful to save both the warnings and the output, and decide what to do later. See http://stackoverflow.com/q/4948361/210673. This uses the same methods that @MartinMorgan suggests. – Aaron left Stack Overflow Mar 08 '13 at 15:01

2 Answers2

15

I think you're looking for the difference between tryCatch, which catches a condition and continues evaluation from the environment where the tryCatch was defined, versus withCallingHandlers, which allows you to 'handle' a condition and then continue on from the location where the condition occurred. Take a look at warning (or the help page for warning, but that's less fun), especially the lines

    withRestarts({
        .Internal(.signalCondition(cond, message, call))
        .Internal(.dfltWarn(message, call))
    }, muffleWarning = function() NULL)

This says -- signal a condtion, but insert a 'restart' where the condition was signaled from. Then you'd

withCallingHandlers({
    warning("curves ahead")
    2
}, warning = function(w) {
    ## what are you going to do with the warning?
    message("warning occurred: ", conditionMessage(w))
    invokeRestart("muffleWarning")
})

Although withCallingHandlers is often used with warnings and tryCatch with errors, there is nothing to stop one from 'handling' an error or catching a warning if that is the appropriate action.

Martin Morgan
  • 45,935
  • 7
  • 84
  • 112
  • Wow, thanks man! Don't fully comprehend it yet and have to play it through with some of my own examples, but that looks *really* powerful! Awesome! – Rappster Mar 08 '13 at 14:59
  • Martin, would you mind posting a little example that explains how `withRestarts()`, `simpleCondition()`, `signalCondition()` and `withCallingHandlers()` interact? I'm having trouble understanding args `cond`, `message` and `call` and your `expr` part of `withRestarts()` seems to be a bit more complex than those explained on the help page. Thanks a lot! – Rappster Mar 12 '13 at 09:48
  • 1
    I think I got the basic idea now. Consider this to be a great example: http://www.win-vector.com/blog/2012/10/error-handling-in-r/?utm_source=rss&utm_medium=rss&utm_campaign=error-handling-in-r. Thanks again, really helpful! – Rappster Mar 12 '13 at 12:03
2

You can recall the forecast within the warning section, something like this:

mod <- tryCatch(
  out <- forecast::auto.arima(x=y),
  error=function(e) {
    print(e)
  },
  warning=function(w) {
    print(w)
    out <- forecast::auto.arima(x=y)
    return(out)
  }
)

This will print a warning , but the result of forecast is stored in mod now.

<simpleWarning in kpss.test(x): p-value smaller than printed p-value>
> mod
Series: y 
ARIMA(4,1,1)                    

Coefficients:
         ar1      ar2     ar3      ar4      ma1
      0.6768  -0.2142  0.5025  -0.7125  -0.8277
s.e.  0.0749   0.0889  0.0874   0.0735   0.0485

sigma^2 estimated as 915556:  log likelihood=-780.33
AIC=1572.65   AICc=1573.62   BIC=1587.91
agstudy
  • 119,832
  • 17
  • 199
  • 261
  • 2
    it is unefficient in case of heavy computation/processing. It solves the problem from a theoretical point of view but not at all from a practical one. – Colonel Beauvel Jan 06 '16 at 10:51
  • 1
    In any case I claim that the solution is efficient and the OP don't even ask for efficiency. Your comment is maybe theorically correct( I should test the solution in a big data context , by the way you should explain what do you mean by "heavy computation"), But in practice this comment is uneseful. – agstudy Jan 06 '16 at 12:03
  • 1
    This is a bad solution since it doesn't reuse the result of `out`, but rather recomputes it on a warning. – Davor Josipovic Jul 09 '20 at 13:14