【问题标题】:Use tryCatch with a while loop in R在 R 中使用带有 while 循环的 tryCatch
【发布时间】:2015-12-28 16:57:08
【问题描述】:

我正在尝试在 R 中使用 while 循环实现 tryCatch,但遇到了问题。我尝试实施一些建议的解决方案(围绕 for 循环),但没有成功。

本质上,我正在使用 R 查询 API 并循环访问许多相关参数(准确地说是经度和纬度)。我需要一个 tryCatch 块的原因是有时 URL 请求会失败,这反过来会停止脚本运行。我想要做的是忽略错误,将循环计数器增加 1 并继续提取。

我设置的 while 循环是(仅供参考 - 长度是指被循环的数据帧的长度):

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

while 循环的输入 data.frame 看起来像这样(注意我在字符串中抛出了一个错误以测试 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 和其他解决方案,但结果似乎无法正常工作。有人可以帮忙吗?

谢谢!

杰克

【问题讨论】:

  • 如果您在数据框中包含一些示例参数,这可能会有所帮助。
  • 嗨。这是一个非常简单的 data.frame(如果我理解正确的话)。我已经用输入 df 的头部更新了这个问题。谢谢!
  • 你为什么使用while??好像for (i in 1:length) tryCatch({...}) 正在工作。
  • 您好。我更改为 for 循环,现在它工作正常,实际上我可以通过尝试而不是 tryCatch 来逃脱。虽然我仍然很想知道为什么它不适用于 while 循环?谢谢大家,很有用!
  • 我在下面详细写了一个答案,并意识到这是给try而不是tryCatch。哎呀。

标签: r error-handling while-loop try-catch-finally


【解决方案1】:

作为一般说明 - 您的代码有点奇怪。我会推荐一个 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(),这可能代表了一种不同的方式,所以我想我会留下它。

【讨论】:

    【解决方案2】:

    在评论的好心人的帮助下,我得到了答案。基本上完全避免了 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}
    )
    }
    

    【讨论】:

    • 我最终取消了删除我最初写的答案,因为无论如何您决定使用try 而不是tryCatch。希望不同的版本有意义。
    猜你喜欢
    • 2015-06-01
    • 2017-06-07
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    相关资源
    最近更新 更多