47

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 Answers 4

58

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)
}
Sign up to request clarification or add additional context in comments.

4 Comments

Use tryCatch instead of try, cleaner syntax and more control in my opinion.
@Hansi: Agreed that tryCatch is cleaner once you know it, though it takes a bit longer to understand, so I figured try is more appropriate for a VBA programmer. <*ducks*>
@TMS Wow I can't believe that's been a wrong answer for 6 years.
@RichieCotton :-D
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)
}

6 Comments

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?
I'd use a function: try([insert a function here])
Or use a semicolon: try( {a<-1; 2+2} )
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.
@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!
|
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.

Comments

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.