循环中重复值,直到错误消失

时间:2017-06-11 16:55:05

标签: r loops error-handling try-catch

我目前正在使用for循环使用Googleway软件包对大量地址进行地理编码。最初,我遇到了" 500内部服务器错误的问题"停止执行循环。我能够使用tryCatch()解决这个问题。但是,由于这往往是一个瞬态错误,我希望该函数重复抛出错误的地址,直到它收到结果或达到一定数量的尝试,让我们说10。

不幸的是,我发现tryCatch()和与之相关的文档令人困惑,所以除了让它抛出错误信息并继续前进之外,我不知道该怎么做。这是我目前的代码:

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)
              }

1 个答案:

答案 0 :(得分:6)

您可能希望将安全调用google_geocode()的逻辑与循环地址分开。

这是一个修改其他函数的函数,可以重复调用它们直到它们工作,或者它们失败max_attempts次。修改其他功能的功能有时称为“副词”。

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
  }
}

尝试使用这个生成随机数的简单函数,如果它太小则抛出错误。

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

在这种情况下,您要修改google_geocode()功能。

safe_google_geocode <- safely(google_geocode)

然后遍历调用此地址的地址。

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