我的 R 代码有时会返回
NA
,这会导致下游错误。 然而,它失败的唯一原因是随机数不好。使用不同的起点再次运行该表达式,它生成的结果不是 NA
。
我设置了一个
while
循环,在放弃之前多次尝试该表达式。这是一个例子:
attempts <- 0
x <- NA
while(is.na(x) & attempts < 100) {
attempts <- attempts + 1
rand <- runif(1)
x <- ifelse(rand > 0.3, rand, NA)
}
if(attempts == 100) stop("My R code failed")
x
我不喜欢这太笨重了。
是否有函数、包或方法可以帮助简化这个 try-repeat-try-again 表达式?
1) 我们可以将其变成一个函数,如果找到一个则返回
x
,如果没有则停止。 我们还使用 for
代替 while
,使用 if
代替 ifelse
。
retry <- function() {
for(i in 1:100) {
rand <- runif(1)
x <- if (rand > 0.3) rand else NA
if (!is.na(x)) return(x)
}
stop("x is NA")
}
retry()
2) 或者如果您不想在函数中停止,则删除
stop
行,将其替换为返回 x 的行,然后使用它(尽管它确实涉及测试 x 的 NA 两次):
x <- retry()
if (is.na(x)) stop("x is NA")
3) 或另一种选择是将错误值传递给函数。 由于惰性评估,
bad
参数仅在实际上不好时才被评估:
retry2 <- function(bad) {
for(i in 1:100) {
rand <- runif(1)
x <- if (rand > 0.3) rand else NA
if (!is.na(x)) return(x)
}
bad
}
retry2(stop("x is NA"))
4) 如果您不介意使用
break
测试 x 的 NA 两次,即使没有函数也可以工作:
for(i in 1:100) {
rand <- runif(1)
x <- if (rand > 0.3) rand else NA
if (!is.na(x)) break
}
if (is.na(x)) stop("x is NA")
x
我使用
retry
包做了一些类似的事情,取得了一些成功,该包具有重复运行代码直到满足某些条件的功能。
https://cran.r-project.org/package=retry
我的情况与你的有点不同,因为我生成/发送电子邮件的代码会定期失败,所以我想重新运行它,直到返回条件不为 NULL。
retry::retry({
# original code to compose an email,
# add some attachments and then send
},
until = \(val, condition) { is.null(condition) },
max_tries = 10)
我想如果你改变
until
函数,你可以测试返回值,例如
until = \(val, condition) { !is.na(val) }