45

I have written an R script which includes a loop that retrieves external (web) data. The format of the data are most of the time the same, however sometimes the format changes in an unpredictable way and my loop is crashing (stops running).

Is there a way to continue code execution regardless the error? I am looking for something similar to "On error Resume Next" from VBA.

Thank you in advance.

4 Answers4

57

Use try or tryCatch.

for(i in something)
{
  res <- try(expression_to_get_data)
  if(inherits(res, "try-error"))
  {
    #error handling code, maybe just skip this iteration using
    next
  }
  #rest of iteration for case of no error
}

The modern way to do this uses purrr::possibly.

First, write a function that gets your data, get_data().

Then modify the function to return a default value in the case of an error.

get_data2 <- possibly(get_data, otherwise = NA)

Now call the modified function in the loop.

for(i in something) {
  res <- get_data2(i)
}
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
8

You can use try:

# a has not been defined
for(i in 1:3)
{
  if(i==2) try(print(a),silent=TRUE)
  else print(i)
}
MånsT
  • 904
  • 5
  • 19
  • Thanks for the quick response. In case that I want to apply the "try" in code that expands to multiple lines what is the syntax? – Financial Economist Jan 13 '12 at 15:00
  • I'd use a function: `try([insert a function here])` – MånsT Jan 13 '12 at 15:10
  • Or use a semicolon: `try( {a<-1; 2+2} )` – MånsT Jan 13 '12 at 15:23
  • 1
    The problem is that every questionable code fragment needs to be wrapped. For example, if I want to quickly test something, I know that middle of the script might give an error, but it is fine with me. It is inconvenient to wrap every single block. `try` or `tryCatch` is definitely not an answer for OP problem. – mlt Dec 17 '12 at 23:18
  • @mit: I agree that this is a slightly awkward solution. If you have a better proposal, I'd be most interested to hear more about it! – MånsT Dec 18 '12 at 07:55
  • @mlt, MånsT Agreed. See new answer on related question : http://stackoverflow.com/a/14612524/403310 – Matt Dowle Jan 30 '13 at 21:52
5

How about these solutions on this related question :

Is there a way to `source()` and continue after an error?

Either parse(file = "script.R") followed by a loop'd try(eval()) on each expression in the result.

Or the evaluate package.

Community
  • 1
  • 1
Matt Dowle
  • 58,872
  • 22
  • 166
  • 224
0

If all you need to do is a small piece of clean up, then on.exit() may be the simplest option. It will execute the expression "when the current function exits (either naturally or as the result of an error)" (documentation here).

For example, the following will delete my_large_dataframe regardless of whether output_to_save gets created.

on.exit(rm("my_large_dataframe"))

my_large_dataframe = function_that_does_not_error()
output_to_save = function_that_does_error(my_large_dataframe)
Simon.S.A.
  • 6,240
  • 7
  • 22
  • 41