1

My problem is very similar to what is described here but unfortunately I am unable to apply the code in the specific situation I am in.

So I am trying to download many URLs and I am using a for loop to get this done. This is how my loop might look like:

ids <- c("1", "3", "7", "9")

numbers <- list()
  for (jj in seq_along(ids)) {  
   numbers[[jj]] <- as.numeric(ids[jj])
      }

That works all dandy. Until I receive the Error "Error: Try Again", which randomly appears but can be fixed if I just start the loop again at the same place.

However, there is a different error which signals that the API key I am using has expired "Error: Stop for loop", and for this error I need to stop the loop, restart the API key manually (can't be automated unfortunately) and then start again at the iterator where it left off.

So to simulate this I wrote this little loop:

errors <- c("Error: Try Again", "Error: Stop for loop")

numbers <- list()
  for (jj in seq_along(ids)) {  
   numbers[[jj]] <- as.numeric(ids[jj])
    if (jj == sample(1:4, 1)) stop(sample(errors, 1)) 
   #randomly stops and gives one or the other error
  }

So here is what I want to do:

  1. Whenever my for loop hits "Error: Try Again", I want the loop to try again until it works.

  2. Whenever my for loop hits "Error: Stop for loop", I want the loop to stop so I can manually fix the API key error. In this case I want the results of the loop saved, so I can later rbind them together when I restart the loop.

Unfortunately, I am very unskilled in writing these kind of conditions. I know that I have to use try or tryCatch somehow but I am unable to figure out how I can test for specific error messages (rather than if an error occured at all).

Thank you for the help everyone!

FaV1
  • 65
  • 5
  • it's just an illustration because my actual loop code would have required the packages and I wanted an easy reproducible example that conveys the idea – FaV1 Dec 13 '17 at 20:09
  • That makes sense, after reading your question a little more carefully I figured that was the case. – Gregor Thomas Dec 13 '17 at 20:11

1 Answers1

1

I think something like this is good. I pulled the error-generating part into its own function to make things more modular and easier to understand.

To easily "try things until success", a while loop makes more sense than a for loop. We can break to stop the loop. I've used next to jump to the next iteration of the loop, though it really isn't needed here (using it would skip everything left in the loop for the current iteration - but since there's really nothing that happens after my next statements they could be left out).

ids <- c("1", "3", "7", "9", "12", "13", "18")

foo = function() {
    errors <- c("Error: Try Again", "Error: Stop for loop")
    if (runif(1) < 0.25) stop(sample(errors, 1))
}

numbers <- list()
jj = 1
while(jj <= length(ids)) {
    numbers[[jj]] <- as.numeric(ids[jj])
  outcome = tryCatch(foo(), error = function(e) e)
  if (is.null(outcome)) {
    jj = jj + 1
    next
  } else if (outcome$message == "Error: Stop for loop") {
    message("Loop stopped on iteration ", jj)
    break
  } else if (outcome$message == "Error: Try Again"){
    next
  }
}
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294