1

I'm working on a loop, and I want to extract the index causing an error in R and put it into a separate object.

Here is an example modified from an answer in a stack overflow post. It skips and reports the nature of the error.

for (i in 1:15) {
  tryCatch({
    print(i)
    if (i==7) stop("Urgh, the iphone is in the blender !")
    if (i==9) stop("Urgh, the iphone is in the blender !")
    if (i==14) stop("Urgh, the iphone is in the blender !")

  }, error=function(e){cat("ERROR :",conditionMessage(e), "\n")})
}

In addition to skipping and reporting the error, how can I improve this code to create a separate object with the index causing the error? Such that, it creates an object, Index Error, with 7, 9, and 14 inside it.

Thank You!

Sharif Amlani
  • 1,138
  • 1
  • 11
  • 25

2 Answers2

2

You can try using <<- operator to save the index of the error.

var <- c()
for (i in 1:15) {
  tryCatch({
    print(i)
    if (i==7) stop("Urgh, the iphone is in the blender !")
    if (i==9) stop("Urgh, the iphone is in the blender !")
    if (i==14) stop("Urgh, the iphone is in the blender !")
    
  }, error=function(e){
    cat("ERROR :",conditionMessage(e), "\n")
    var <<- c(var, i)
    })
}

var
#[1]  7  9 14
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
2

Here are two ways, both with a lapply loop, only different in what the error function returns.
The error messages are displayed with message, not cat. This is because the use of cat or print in packages is frowned upon.

1. Return the index i

result <- lapply(1:15, function(i) {
  tryCatch({
    print(i)
    if (i==7) stop("Urgh, the iphone is in the blender !")
    if (i==9) stop("Urgh, the iphone is in the blender !")
    if (i==14) stop("Urgh, the iphone is in the blender !")
    
  }, error=function(e){
    msg <- paste("ERROR :", conditionMessage(e))
    message(msg)
    i
  })
})
#[1] 1
#[1] 2
#[1] 3
#[1] 4
#[1] 5
#[1] 6
#[1] 7
#ERROR : Urgh, the iphone is in the blender !
#[1] 8
#[1] 9
#ERROR : Urgh, the iphone is in the blender !
#[1] 10
#[1] 11
#[1] 12
#[1] 13
#[1] 14
#ERROR : Urgh, the iphone is in the blender !
#[1] 15

unlist(result)
#[1]  7  9 14

2. Return the error e

This solution returns the error itself, which can latter be retrieved. The output of message is ommited.

result <- lapply(1:15, function(i) {
  tryCatch({
    print(i)
    if (i==7) stop("Urgh, the iphone is in the blender !")
    if (i==9) stop("Urgh, the iphone is in the blender !")
    if (i==14) stop("Urgh, the iphone is in the blender !")
    
  }, error=function(e){
    msg <- paste("ERROR :", conditionMessage(e))
    message(msg)
    e
  })
})

err <- which(sapply(result, inherits, "error"))
err
#[1]  7  9 14

result[[14]]$message
#[1] "Urgh, the iphone is in the blender !"
Rui Barradas
  • 70,273
  • 8
  • 34
  • 66