5

I'm looking for a simple way to move on to the next iteration in a for loop in R if the operation inside the for loop errors.

I've recreated a simple case below:

for(i in c(1, 3)) {
  test <- try(i+1, silent=TRUE)
  calc <- if(class(test) %in% 'try-error') {next} else {i+1}
  print(calc)
}

This correctly gives me the following calc values.

[1] 2
[1] 4

However once I change the vector in i to include a non-numeric value:

for(i in c(1, "a", 3)) {
  test <- try(i+1, silent=TRUE)
  calc <- if(class(test) %in% 'try-error') {next} else {i+1}
  print(calc)
}

This for loop doesn't work. I was hoping for the same calc values as above with the vector excluding the non-numeric value in i.

I tried using tryCatch as the following:

for(i in c(1, "a", 3)) {
  calc <- tryCatch({i+1}, error = function(e) {next})
  print(calc)
}

However, I get the following error:

Error in value[[3L]](cond) : no loop for break/next, jumping to top level 

Could someone please help me understand how I could achieve this using a for loop in R?

5
  • 3
    You might want to examine what c(1, "a", 3) actually is. I think you believe that only the middle element is character but that is incorrect. Commented Sep 7, 2016 at 14:36
  • 2
    I'm not sure why you're trying to do this though. Is this a simplified example? If it isn't then just using as.numeric on the input vector will make the characters into NA. Play around with it as.numeric(c(1, "k", "3")) + 1 Commented Sep 7, 2016 at 14:38
  • @Dason I'm actually more interested in error handling of the control flow within the for loop example as this is just a simplified case of a larger script I have. I only violated the definition of vector in i by putting a character element to recreate a scenario that throws out an 'Error'. Hope this clarifies my question. Commented Sep 7, 2016 at 14:50
  • The issue you created with your example though is that you created all errors. You didn't leave a good case. Commented Sep 7, 2016 at 14:59
  • What output do you want from this? Do you want a vector of where the errors are, or a vector of the valid results? Commented Sep 7, 2016 at 17:52

2 Answers 2

1

As Dason noted, an atomic vector really is not the best way of storing mixed data types. Lists are for that. Consider the following:

l = list(1, "sunflower", 3)

for(i in seq_along(l)) {
   this.e = l[[i]]
   test <- try(this.e + 1, silent=TRUE)
   calc <- if(class(test) %in% 'try-error') {next} else {this.e + 1}
   print(calc)
}

[1] 2
[1] 4

In other words, your former loop "worked". It just always failed and went to next iteration.

Sign up to request clarification or add additional context in comments.

Comments

1

Here is a solution using the "purr" package that might be helpful. It goes through your list or vector and returns the elements that will cause errors

#Wrap the function you want to use in the adverb "safely" 
safetest <- safely(function(x){ifelse(is.na(as.numeric(x)),
                                  x+1,
                                  as.numeric(x)+1)})

myvect<-c(1,"crumbs",3) #change to list if you want a list

#Use the safe version to find where the errors occur
check <- myvect  %>% 
  map(safetest) %>%
  transpose %>% .$result %>% 
  map_lgl(is_null)

myvect[check]

#This returns the results that did not through an error
#first remove NULL elements then flatten to double.
#The two flatten expresiion can be replaced by a single unlist
myvect  %>% 
  map(safetest) %>%
  transpose %>% .$result %>% 
  flatten()%>%flatten_dbl()

see https://blog.rstudio.org/2016/01/06/purrr-0-2-0/ for the original example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.