2015-09-30 112 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