2017-06-11 40 views
3

私は現在、forループを使用して、Googlewayパッケージを使用して多数のアドレスをジオコーディングしています。最初は、ループの実行を停止する「500内部サーバーエラー」の問題が発生しました。私はtryCatch()を使ってこれを回避することができました。しかし、これは一時的なエラーであることが多いので、結果を受け取ったり、何らかの試行に達するまでエラーをスローするアドレスを繰り返すようにしたいと思います。エラーがなくなるまでループ内の値を繰り返す

残念ながら、私は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) 
       } 

答えて

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 
) 
+1

なぜ 'this_env < - environment() 'を使用したのか分かりますか?環境はここでは少し複雑ですが、オブジェクトに代入するために結果がsafe()関数で作成されたクロージャからグローバル環境にどのように移動するのかを追うのには問題があります。 –

+1

@SeanNortonうん、それは混乱している。 'tryCatch()'はそれ自身の環境を使用しているように見えるので、 'result < - fn(...)'を実行するだけで動作しません。 –

+0

@SeanNorton 'this_env'は' safe_whatever() 'クロージャーに属する環境だと思います。 –

関連する問題