R:使用 tryCatch() 在循环中跳过请求失败 [500] 错误失败

Posted

技术标签:

【中文标题】R:使用 tryCatch() 在循环中跳过请求失败 [500] 错误失败【英文标题】:R: Failure to skip request failed [500] errors in loop using tryCatch() 【发布时间】:2022-01-15 06:41:44 【问题描述】:

我查看了几个不同的相关问题:

Use tryCatch skip to next value of loop upon error? How to use Trycatch to skip errors in data downloading in R(这个可能和我的问题最相似)

我想遍历数据帧中的坐标并使用 USGS nhdplustools 包中的 discover_nhdplus_id() 函数来搜索最近的下坡流并将该流的 ID 号 (COMID) 记录在矩阵中。如果遇到错误,我希望循环记录“NA”并移动到下一个坐标。

示例数据框(这里有两对坐标无法返回结果:0,0 和 -111.2395, 36.5396):

# Minimal example dataframe

y <- c(38.27691,
       38.440779,
       37.784306,
       0,
       36.5396,
       38.293296,
       36.5375
)
x <- c(-112.64105,
       -111.643221,
       -111.633194,
       0,
       -111.2395,
       -111.550817,
       -111.2371
)

test_df <- data.frame(x, y)

理想情况下,输出应如下所示:

[1] 1215201
[1] 4900445
[1] 3277825
[1] NA
[1] NA
[1] 944070011
[1] 3528735

但是,当我实现 tryCatch() 时,遇到错误时循环仍然会崩溃。这些往往是“请求失败 [500]”错误。这是我的 tryCatch() 尝试:

library(nhdplusTools)

output <- matrix(NA, nrow=nrow(test_df), ncol=1)
colnames(output) <- c("COMID_raindrop")

for (i in 1:nrow(test_df))
  
  latitude <- test_df$y[i]
  longitude <- test_df$x[i]
  
  start_point <- st_sfc(st_point(c(longitude, latitude)), crs = 4269)
  
  raindrop_trace <- tryCatch(
      
        discover_nhdplus_id(start_point)
      ,
      error = function(e) 
        NA
      
    )
  
  output[i] <- raindrop_trace
  print(raindrop_trace)
  


[1] 1215201
[1] 4900445
[1] 3277825
No data returned for: https://labs.waterdata.usgs.gov/api/nldi/linked-data/comid/position?coords=POINT%280%200%29FALSE
Request failed [500]. Retrying in 1.2 seconds...
Request failed [500]. Retrying in 1 seconds...
Error in: https://labs.waterdata.usgs.gov/api/nldi/linked-data/comid/NULL/
Error in output[i] <- raindrop_trace : replacement has length zero

在查找有关此的信息时,我看到 purrr::possibly 推荐,但是当我尝试实现时返回不同的错误:

output <- matrix(NA, nrow=nrow(test_df), ncol=1)
colnames(output) <- c("COMID_raindrop")

for (i in 1:nrow(test_df))
  
  latitude <- test_df$y[i]
  longitude <- test_df$x[i]
  
  start_point <- st_sfc(st_point(c(longitude, latitude)), crs = 4269)
  
  get_data <- discover_nhdplus_id(start_point)
  raindrop_trace <- purrr::possibly(get_data, otherwise = NA) 
  
  output[i] <- raindrop_trace
  print(raindrop_trace) 
  


Error in output[i] <- raindrop_trace : 
  incompatible types (from closure to logical) in subassignment type fix

我认为这个错误可能与分配“NA”(一个非数字值)有关,但是在分配 else = 0 时我得到了同样的错误。

非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

您需要添加带有返回函数的NA 以将其写入您的输出。

编辑:

您可以只扫描messages 并使用withCallingHandlers 基于它们创建一个错误。我添加了你有问题的坐标 (cmets) 来测试它。

library(nhdplusTools)
library(sf)
    
y <- c(38.27691,
       38.440779,
       37.784306,
       0,
       0,
       38.293296,
       36.5375,
       36.5396)

x <- c(-112.64105,
       -111.643221,
       -111.633194,
       0,
       0,
       -111.550817,
       -111.2371,
       -111.2395)

test_df <- data.frame(x, y)
test_df <- st_as_sf(x = test_df, coords = c("x", "y"), crs = 4269)

output <- matrix(NA, nrow=nrow(test_df), ncol=1)
colnames(output) <- c("COMID_raindrop")

for (i in seq_along(test_df[[1]]))
  start_point <- test_df[i,]
  
  raindrop_trace <- tryCatch(
    
      withCallingHandlers(discover_nhdplus_id(point = start_point), message = function(c) if (inherits(c, "message"))stop(""))
      discover_nhdplus_id(point = start_point)
    ,
    error = function(e) 
      return(NA)
    
  )
  output[i] <- raindrop_trace
  print(raindrop_trace)


[1] 1215201
[1] 4900445
[1] 3277825
[1] NA
[1] NA
[1] 944070011
[1] 3528735
[1] NA

【讨论】:

感谢您的浏览。这也适用于示例数据集。我希望有一种方法可以优雅地处理更多难以预料的错误情况——我正在使用一个非常大的坐标表,许多看起来有效的坐标会导致循环崩溃。例如:“-111.2395, 36.5396”。我不确定如何自动处理这些问题。 我编辑了答案。我认为这是一个通用的解决方案,但它又不是很优雅。虽然可能比上一个更重要。 这是我所希望的。我不熟悉 withCallingHandlers() - 需要阅读更多内容。非常感谢!

以上是关于R:使用 tryCatch() 在循环中跳过请求失败 [500] 错误失败的主要内容,如果未能解决你的问题,请参考以下文章

为啥 .setValue() 在 for 循环中跳过列?

使用 CSV 文件在循环中跳过第一行(字段)? [复制]

如何在 ddd (gdb) 中跳过过去的循环

Scanf 在循环中跳过(Hangman)

如何在循环中跳过项目

在循环中跳过一组值(在数组中) - Python3