Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching Output of a Library Function

Tags:

r

I'm really at a loss here. I found a couple of threads here on stack overflow on how to redirect the output of a function, but none of it seems to be working in my case.

I'm using arima from the library(forecast) for a lot of (generated) timeseries, and some of them have bad properties, which results in auto.arima() printing out an error and a warning. I'm unable to catch this Error in anyway, be it via tryCatch or capture.output() (which only captures the normal forecast).

The goal is to capture the error message (and warning) thrown by the example below and react to it. So basically at the end i would have the error and the forecast (despite being errorneous) in some variable form.

I appreciate any suggestions, the following is the minimal example to produce the error:

library(forecast)
testt <- c(826,816,839,995,697)
testend <- c(2015,164)
testseries <- ts(testt,end=testend,frequency=365)
auto.arima(testseries)
#tryCatch not working:
testfc <- tryCatch(forecast(auto.arima(testseries),h=1), error=function(e) NA)
#capture.output not working:
result <- capture.output(auto.arima(testseries))
like image 730
wlfbck Avatar asked Dec 22 '15 03:12

wlfbck


2 Answers

You can capture the errors and warnings with the type="message" argument to capture.output. type can be either "output", which captures the function output, or "message", which captures the errors and warnings. The function below uses sapply to allow you to run capture.output once with each argument, storing the results in a list.

capture.errors = function(type, data) {
  sapply(type, function(type) {
    capture.output(auto.arima(data), type=type)
  }, simplify=FALSE)
}

out = capture.errors(c("output","message"), testseries)

out

$output
[1] "Series: data "                                    
[2] "ARIMA(0,0,0) with non-zero mean "                 
[3] ""                                                 
[4] "Coefficients:"                                    
[5] "      intercept"                                  
[6] "       834.6000"                                  
[7] "s.e.    42.4746"                                  
[8] ""                                                 
[9] "sigma^2 estimated as 9020:  log likelihood=-29.86"
[10] "AIC=63.73   AICc=69.73   BIC=62.94"               

$message
[1] "Error in arima(x, order = c(1, d, 0), xreg = xreg) : "
[2] "  non-stationary AR part from CSS"                    
[3] "In addition: Warning message:"                        
[4] "In auto.arima(data) : Unable to calculate AIC offset" 

Since capturing the model output with capture.output probably isn't as useful as capturing the "real" output in the model object, maybe the function below would be better. It returns a list with the model object and any error or warning messages:

capture = function(data) {
list(model=auto.arima(data),
     message=capture.output(auto.arima(data), type="message"))
}

The model object is available in the usual way, so below I just look at the message output.

out1 = capture(testseries)

# Show any errors and warnings
out1[["message"]]
[1] "Error in arima(x, order = c(1, d, 0), xreg = xreg) : "
[2] "  non-stationary AR part from CSS"                    
[3] "In addition: Warning message:"                        
[4] "In auto.arima(data) : Unable to calculate AIC offset" 

out2 = capture(cumsum(rnorm(100)))

# No errors or warnings with this data set
out2[["message"]]
character(0)
like image 166
eipi10 Avatar answered Nov 20 '22 08:11

eipi10


If I understand correctly, you are wanting to suppress printing of the error message. (That at least appears to be the goal of your call to tryCatch().) One way to do that is to, immediately before your call to auto.arima(), divert any error messages to a temporary file, using sink(..., type="message"). Then, right after the call, clean up by stopping sinking to the file and then deleting it.

Here's one way you could implement that:

muffleMessages <- function(expr) {
    f <- tempfile()
    ff <- file(f, open="w")
    sink(ff, type="message")
    on.exit({sink(); unlink(f)})
    expr
}

muffleMessages(auto.arima(testseries))
# Series: testseries 
# ARIMA(0,0,0) with non-zero mean 
# 
# Coefficients:
#       intercept
#        834.6000
# s.e.    42.4746
#  
# sigma^2 estimated as 9020:  log likelihood=-29.86
# AIC=63.73   AICc=69.73   BIC=62.94
like image 4
Josh O'Brien Avatar answered Nov 20 '22 07:11

Josh O'Brien