我正在尝试在for循环中处理两个可能的错误,该循环调用stplanr::dist_google
与API进行交互。我知道这些错误,因此我想在发生错误时采取具体措施。
如果我仅尝试处理一种可能的错误,则它可以起作用:
data(cents, package = "stplanr")
data(flow, package = "stplanr")
od <- stplanr::od2odf(flow=flow, zones=cents)
uma_linha <- data.frame(from_addresses=NA, to_addresses=NA, distances=NA,
duration=NA, currency=NA, fare=NA)
output <- data.frame()
for (linha in 1:nrow(od)) {
o <- od[linha, 3:4]
d <- od[linha, 5:6]
output <- tryCatch(
{
rbind(output, stplanr::dist_google(from = o, to = d,
mode = 'walking'))
},
error = function(na) {
message("Erro: No results for this request (e.g. due to lack of support for this mode between the from and to locations)")
message(na)
output <- rbind(output, uma_linha)
}
)
}
我需要获得2500多个观察结果。然后,自动使用两个API。我试图将其他信息和一些小技巧作为一种动作。当我调用循环时,我反复收到两条错误消息。
n <- 1
apis <- c("api01", "api02", "api03")
for (linha in 1:nrow(od)) {
o <- od[linha, 3:4]
d <- od[linha, 5:6]
output <- tryCatch(
{
rbind(output, stplanr::dist_google(from = o, to = d,
mode = 'walking',
google_api = apis[n]))
},
error = function(na) {
message("Erro: No results for this request (e.g. due to lack of support for this mode between the from and to locations)")
message(na)
output <- rbind(output, uma_linha)
},
error = function(quota) {
message("Erro: You have exceeded your daily request quota for this API.")
message(quota)
n <- n + 1
return(n)
}
)
}
我对tryCatch感到困惑。我在做什么错了?
非常感谢您的帮助。
编辑
在马丁明确解释之后,我试图将所有内容放入函数中。它不起作用。
如果错误是:
No results for this request (e.g. due to lack of support for this mode between the from and to locations)
然后函数将继续并返回一个空对象。配额结束且错误为:
You have exceeded your daily request quota for this API.
它递归地返回一个错误,而不是执行n <- n + 1
并继续循环:
asha_dists <- function(fluxo, zonas, api) {
zonas <- as(st_transform(zonas, 4326), "Spatial")
od <- stplanr::od2odf(flow = fluxo, zones = zonas)
uma_linha <- data.frame(from_addresses=NA, to_addresses=NA, distances=NA,
duration=NA, currency=NA, fare=NA)
n <- 1
output <- data.frame()
for (linha in 1:nrow(od)) {
o <- od[linha, 3:4]
d <- od[linha, 5:6]
output <- tryCatch(
{
rbind(output, stplanr::dist_google(from = o, to = d,
mode = 'walking', google_api = api[n]))
},
custom_error = function(e) {
err <- conditionMessage(e)
message("found custom_error: ", err)
output <- rbind(output, uma_linha)
},
error = function(e) {
err <- conditionMessage(e)
message("found an error: ", err)
n <- n + 1
}
)
}
return(output)
}
Sent this request: https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=-23.5678377804732,-46.5708261676873&destinations=-23.5706647015703,-46.5755950203842&mode=walking&key=AIzaSyBRPrAjSE_pRMWSq_XlO4BFwGD63j_gB4U
found an error: You have exceeded your daily request quota for this API.
Sent this request: https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=-23.5665596480444,-46.5682308348154&destinations=-23.5706647015703,-46.5755950203842&mode=walking&key=AIzaSyBRPrAjSE_pRMWSq_XlO4BFwGD63j_gB4U
found an error: You have exceeded your daily request quota for this API.
我只是被困住了。
答案 0 :(得分:3)
有两种捕获错误类型的方法,这取决于错误的产生方式。这是一个会产生错误的函数
f <- function(type) {
switch(
type,
a = stop("oops a: type 1 error"),
b = stop("oops b: type 2 error"),
c = {
err <- simpleError("oop 2: custom error class")
class(err) <- c("custom_error", class(err))
stop(err)
}
)
}
如果type
是“ a”或“ b”,则该函数会生成标准错误条件,但带有不同的条件消息(“ oops a:...”和“ oops b:...”) 。如果type
为“ c”,则该错误具有特定的类“ custom_error”,该类扩展了标准错误的(S3)类。
> f("a")
Error in f("a") : oops a: type 1 error
> f("b")
Error in f("b") : oops b: type 2 error
> f("c")
Error: oop 2: custom error class
这是一个捕获错误的函数。
g <- function(type) {
tryCatch({
f(type)
}, custom_error = function(e) {
err <- conditionMessage(e)
message("found custom_error: ", err)
}, error = function(e) {
err <- conditionMessage(e)
if (startsWith(err, "oops a")) {
message("found type 'a' error: ", err)
} else if (startsWith(err, "oops b")) {
message("found type 'b' error: ", err)
} else {
message("generic error: ", err)
}
})
}
tryCatch的处理程序参数按照在参数列表中出现的顺序进行测试,如果它们与错误的类匹配,则对它们进行评估。类型“ a”或“ b”的错误具有相同的类,因此由同一处理程序捕获;区分它们的唯一选择是“抓取”错误消息以查看条件(错误)消息,以确定一个人正在处理的错误的类型(希望程序包不那么复杂以至于包括错误消息翻译,例如base R可以,因为通常不可能以健壮的方式抓取翻译后的错误...)
> g("a")
found type 'a' error: oops a: type 1 error
> g("b")
found type 'b' error: oops b: type 2 error
另一方面,处理程序可以捕获类型“ c”,因为它具有自己的类。所以...
> g("c")
found custom_error: oop 2: custom error class
一个人实际上可以沿着错误处理程序或向上调用堆栈传递错误
h <- function(type) {
tryCatch({
f(type)
}, custom_error = function(e) {
err <- conditionMessage(e)
message("found custom_error: ", err)
stop(e)
}, error = function(e) {
err <- conditionMessage(e)
message("found an error: ", err)
stop(e)
})
}
使用
> h("c")
found custom_error: oop 2: custom error class
found an error: oop 2: custom error class
Error: oop 2: custom error class
很少有软件包实际使用犯自定义错误的功能,因此您可能会想尝试抓取您看到的错误。对于您的情况,看来您必须抓取,所以
output <- tryCatch({
rbind(
output,
stplanr::dist_google(
from = o, to = d, mode = 'walking', google_api = api[n]
)
)
}, error = function(e) {
err <- conditionMessage(e)
if (startsWith("No results for this request", err) {
warning(err) # warn instead of error
n <<- n + 1 # '<<-' to update n _outside_ this function
rbind(output, uma_linha) # empty output as result
} else if (startsWith("You have exceeded your daily", err) {
stop(e) # signal the original error
} else {
stop(e) # no error that we know how to handle, signal
}
})