Seymour
Seymour

Reputation: 3264

R - tryCatch - use last iteration index to restart the for loop

I already read documentations and several other question about tryCatch(), however, I am not able to figure out the solution to my class of problem.

The task to solve is: 1)There is a for loop that goes from row 1 to nrow of the dataframe. 2)Execute some instruction 3)In the case of error that would stop the program, instead restart the loop cycle from the current iteration.

Example

for (i in 1:50000) {
...execute instructions...
}

What I am looking for is a solution that in the case of error at the iteration 30250, it restart the loop such that

for (i in 30250:50000) {
...execute instructions...
}

The practical example I am working on is the following:

library(RDSTK)
library(jsonlite)
DF <- (id = seq(1:400000), lat = rep(38.929840, 400000), long = rep( -77.062343, 400000)
for (i in 1 : nrow(DF) {
    location <- NULL
    bo <- 0
    while (bo != 10) {  #re-try the instruction max 10 times per row 
        location <- NULL
        location <- try(location <-  #try to gather the data from internet
                coordinates2politics(DF$lat[i], DF$long[i]))
        if (class(location) == "try-error") {  #if not able to gather the data
            Sys.sleep(runif(1,2,7))  #wait a random time before query again
            print("reconntecting...")
            bo <- bo+1                      
            print(bo)                 
        } else    #if there is NO error
            break   #stop trying on this individual
    }
    location <- lapply(location, jsonlite::fromJSON)
    location <- data.frame(location[[1]]$politics)
    DF$start_country[i] <- location$name[1]
    DF$start_region[i] <- location$name[2]
    Sys.sleep(runif(1,2,7))  #sleep random seconds before starting the new row
}

N.B.: the try() is part of the "...execute instruction..."

What I am looking for is a tryCatch that when a critical error that stops the program happen, it instead restart the for loop from the current index "i".

This program would allow me to automatically iterate over 400000 rows and restart where it interrupted in the case of errors. This means that the program would be able to work totally independently by human.

I hope my question is clear, thank you very much.

Upvotes: 0

Views: 1777

Answers (1)

JDL
JDL

Reputation: 1654

This is better addressed using while rather than for:

i <- 1
while(i < 10000){
  tryCatch(doStuff()) -> doStuffResults
  if(class(doStuffResults) != "try-catch") i <- i + 1
{

Beware though if some cases will always fail doStuff: the loop will never terminate!

If the program will produce a fatal error and need a human restart, then the first line i <- 1 may be replaced (as long as you don't use i elsewhere in your code) with

if(!exists("i")) i <- 1

so that the value from the loop will persist and not be reset to one.

Upvotes: 2

Related Questions