在R中使用带有while循环的tryCatch

在R中使用带有while循环的tryCatch,r,error-handling,while-loop,try-catch-finally,R,Error Handling,While Loop,Try Catch Finally,我试图在R中使用while循环实现tryCatch,但遇到了一些问题。我已经尝试实现了许多建议的解决方案(围绕for循环),但并没有成功 本质上,我是在用R查询一个API,并通过一些相关参数(准确地说是经度和纬度)进行循环。我需要tryCatch块的原因是,有时URL请求会失败,这反过来会停止脚本的运行。我希望能够忽略错误,将循环计数器增加1,然后继续提取 我设置的while循环是(FYI-length指循环的数据帧的长度): 我已经尝试了一些SO和其他解决方案,但结果似乎并不正常。有人能帮忙吗

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

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

我设置的while循环是(FYI-length指循环的数据帧的长度):

我已经尝试了一些SO和其他解决方案,但结果似乎并不正常。有人能帮忙吗

谢谢


杰克

一般来说,你的代码有点奇怪。我会推荐一个
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
}
#最低工作版本
图书馆(RJSONIO)
选项(stringsAsFactors=FALSE)
#使用示例数据创建数据框

地理编码(geocode_area)在发表评论的好心人的帮助下,我得到了答案。基本上完全避免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}
)
}
for(1中的i:长度){
试一试(

{x_cord如果您在data frame.Hi中包含一些示例参数,可能会有所帮助。这是一个非常简单的data.frame(如果我理解正确的话)。我已经用输入df的开头更新了这个问题。谢谢!为什么您使用
看起来像
for(I in 1:length)tryCatch({…})
正在做工作。您好。我改成了for循环,现在它运行良好,事实上我可以通过尝试而不是tryCatch。尽管我仍然有兴趣知道为什么它不能与while循环一起工作?谢谢大家,非常有用!我在下面详细写了一个答案,并意识到它是用于
try
而不是
tryCatch
。哎呀。我最终取消了我最初写的答案,因为你决定使用
try
而不是
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
# 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
}
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}
)
}