I have R code that sometimes returns an NA
, which causes errors downstream. However, the only reason that it fails stems from a bad random number. Run the expression again with a different starting point, and it produces results that are not NA
.
I've setup a while
loop to try the expression multiple times before giving up. Here's an example:
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
I don't like how clunky this is.
Is there a function, package, or method that can help simplify this try-repeat-try-again expression?
1) We could turn it into a function which returns x
if it finds one or stops if not. Also we use for
instead of while
and if
instead of 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) or if you don't want the stop in the function then remove the stop
line replacing it with a line that returns x and then use this (although it does involve testing x for NA twice):
x <- retry()
if (is.na(x)) stop("x is NA")
3) or another option is to pass the bad value to the function. Because of lazy evaluation the bad
argument is only evaluated if it is, in fact, 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) If you don't mind testing x for NA twice using break
also works even without a function:
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