2015-09-30 74 views
2

我試圖用R中的while循環實現tryCatch,但一直在遇到問題。我試圖實現一些建議的解決方案(圍繞循環),但沒有成功。在R中使用tryCatch與while循環

本質上來說,我是用R來查詢一個API,並通過一些相關的參數(精確的經度和緯度)進行循環。我需要tryCatch塊的原因是,有時URL請求會失敗,從而導致腳本停止運行。我想要做的就是忽略錯誤,將循環計數器增加1並繼續提取。

while循環我已成立是(FYI - 長度是指繞環數據幀的長度上):

i <- 1 
while(i <= length) { 
x_cord <- geocode_area$X[i] 
y_cord <- geocode_area$Y[i] 
target <- getUrl(x_cord,y_cord) 
dat <- fromJSON(target) 
geocode_area$Block[i] <- dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK 
print(paste(i/length*100,"% completed",sep="")) 
print(dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK) 
i <- i + 1 
} 

使用getURL()函數定義爲:

getUrl <- function(x,y) { 
root <- "http://geocoding.geo.census.gov/geocoder/geographies/coordinates?" 
u <- paste0(root,"x=", x,"&y=", y,"&benchmark=4&vintage=4&format=json") 
return(URLencode(u)) 
} 

的輸入data.frame到while循環看起來是這樣的(注意我已經拋出字符串來模擬錯誤來測試tryCatch正在工作):

  X     Y   Block 
1 -122.425891675136 37.7745985956747  0 
2 -122.42436302145 37.8004143219856  0 
3 -122.426995326766 37.8008726327692  0 
4 -122.438737622757 37.7715411720578  0 
5    abc   zsads  0 

我已經嘗試了一些SO和其他解決方案,但結果似乎沒有正常工作。誰能幫忙?

謝謝!

插孔

+0

如果您在數據框中包含一些示例參數,它可能會有幫助。 – TARehman

+0

嗨。這是一個非常簡單的數據框架(如果我正確理解你的話)。我已經用輸入df的頭部更新了這個問題。謝謝! –

+1

爲什麼你使用'while'?看起來像'for(i in 1:length)tryCatch({...})'正在做工作。 – Marek

回答

2

作爲一般說明 - 您的代碼有點奇怪。我會建議一個for循環,或者可能更好,一個功能,做這個東西。但你可以讓你的循環工作。

# A minimal working version 
library(RJSONIO) 
options(stringsAsFactors = FALSE) 

# Create a data frame with the example data 
geocode_area <- data.frame(X = c("-122.425891675136","-122.42436302145","-122.426995326766","-122.438737622757","abc"), 
          Y = c("37.7745985956747","37.8004143219856","37.8008726327692","37.7715411720578","zsads"), 
          Block = c(0,0,0,0,0)) 

# Your old function, unchanged 
getUrl <- function(x,y) { 

    root <- "http://geocoding.geo.census.gov/geocoder/geographies/coordinates?" 
    u <- paste0(root,"x=", x,"&y=", y,"&benchmark=4&vintage=4&format=json") 
    return(URLencode(u)) 
} 

# Getting the length parameter 
length <- nrow(geocode_area) 
i <- 1 
while(i <= length) { 

    x_cord <- geocode_area$X[i] 
    y_cord <- geocode_area$Y[i] 
    target <- getUrl(x_cord,y_cord) 

    # Here be new code 
    # Do a try(), with silent = TRUE, which suppresses outputs to STDERR 
    # In principle, this is dangerous - a better approach is to strip out the offending data before invoking it 
    # Errors are, after all, there for a reason 
    dat <- try(fromJSON(target),silent = TRUE) 

    # Now, we conditionally complete the next steps 
    # If the class of dat is not a try-error, perform your normal operations 
    # Otherwise, bypass and print a note to the console 
    if(class(dat) != "try-error") { 

     geocode_area$Block[i] <- dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK 
     print(paste(i/length*100,"% completed",sep="")) 
     print(dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK) 
    } else if (class(dat) == "try-error") {print("Error encountered, bypassing")} 
i <- i + 1 
} 

編輯補充:很顯然,這裏採用的try()代替tryCatch()。然而,由於海報最終使用了try(),這可能代表了一種不同的方式,我認爲我會放棄它。

0

在一些評論我得到答案的人的幫助下。本質上避免使用while循環,而是使用for循環。

我不確定爲什麼while循環不起作用,我認爲這可能與更新finally塊中的循環計數器時遇到困難有關。

事實上,對於我所遇到的具體問題,我根本就不需要tryCatch。我將使用錯誤塊來將我正在更新的值設置爲0,但是可以在for循環中將輸入變量重置爲0。這是必需的,因爲否則將保留先前迭代的值。我也需要在{}中包裝try表達式,因爲有多個表達式。

下面的代碼。我希望這可以幫助別人!

for(i in 1:length) { 
try(
{x_cord <- geocode_area$X[i] 
y_cord <- geocode_area$Y[i] 
target <- getUrl(x_cord,y_cord) 
dat <- fromJSON(target) 
geocode_area$Block[i] <- dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK 
print(paste(i/length*100,"% completed",sep="")) 
print(dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK) 
dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK <- 0} 
) 
} 
+0

我最終放棄了原來寫過的答案,因爲您決定使用'try'而不是'tryCatch'。希望不同的版本是有道理的。 – TARehman