Repeating values ​​in a loop until the error disappears

I am currently using a for loop to geocode a large number of addresses using the Googleway package. Initially I ran into "500 Internal Server Errors" issues stopping the loop from executing. I managed to get around this with tryCatch (). However, since this tends to be a transient error, I would like the function to repeat the address that is throwing the error until it receives a result or hits some arbitrary number of attempts, say 10.

Unfortunately, I found tryCatch () and the documentation associated with it is confusing, so I don't understand how to do anything other than get it to throw an error and move on. Here is my current code:

rugeocoder.fun <- function(addr){
              require(googleway)
              output <- vector("list", length=length(addr))
              tryCatch({
                for(i in 1:length(addr)){
                  output[[i]] <- google_geocode(address=addr[i], key="myapikey", language="ru", simplify=T)
                  print(i)

                }},error=function(e) output[[i]] <- "Error: reattempt")
              return(output)
              }

      

+3


source to share


1 answer


You probably want to isolate the logic for safe invocation google_geocode()

and for address enumeration.

Here's a function that modifies other functions to call them again until they work, or they fail max_attempts

once. Functions that modify other functions are sometimes referred to as "adverbs".

safely <- function(fn, ..., max_attempts = 5) {
  function(...) {
    this_env <- environment()
    for(i in seq_len(max_attempts)) {
      ok <- tryCatch({
          assign("result", fn(...), envir = this_env)
          TRUE
        },
        error = function(e) {
          FALSE
        }
      )
      if(ok) {
        return(this_env$result)
      }
    }
    msg <- sprintf(
      "%s failed after %d tries; returning NULL.",
      deparse(match.call()),
      max_attempts
    )
    warning(msg)
    NULL
  }
}

      

Try this simple function that generates a random number and throws an error if it's too small.

random <- function(lo, hi) {
  y <- runif(1, lo, hi)
  if(y < 0.75) {
    stop("y is less than 0.75")
  }
  y
}
safe_random <- safely(random)
safe_random() # will sometimes work, will sometimes return NULL
safe_random(0, 10) # will usually work

      



In this case, you want to change the function google_geocode()

.

safe_google_geocode <- safely(google_geocode)

      

Then encode the addresses causing this.

geocodes <- lapply( # purrr::map() is an alternative
  addresses,
  safe_google_geocode,
  key = "myapikey", 
  language = "ru", 
  simplify = TRUE
)

      

+6


source







All Articles