Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use tryCatch with a while loop in R

I am trying to implement tryCatch with a while loop in R, but have been running into issues. I have tried to implement a number of the proposed solutions (which revolve around for loops), but with no success.

Essentially I am querying an API with R and looping through a number of relevant parameters (longitudes and latitudes to be precise). The reason why I need a tryCatch block is because sometimes the URL request will fail, which in turn stops the script running. What I want to be able to do is to ignore the error, increase the looping counter by 1 and continue extraction.

The while loop I have set up is (FYI - length refers to length of dataframe being looped over):

i <- 1
while(i <= length) {
x_cord <- geocode_area$X[i]
y_cord <- geocode_area$Y[i]
target <- getUrl(x_cord,y_cord)
dat <- fromJSON(target)
geocode_area$Block[i] <- dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK
print(paste(i/length*100,"% completed",sep=""))
print(dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK)
i <- i + 1 
}

The getUrl() function is defined as:

getUrl <- function(x,y) {
root <- "http://geocoding.geo.census.gov/geocoder/geographies/coordinates?"
u <- paste0(root,"x=", x,"&y=", y,"&benchmark=4&vintage=4&format=json")
return(URLencode(u))
}

The input data.frame to the while loop looks like so (note I have thrown in the character strings to simulate an error to test that tryCatch is working):

          X                 Y          Block
1 -122.425891675136 37.7745985956747     0
2  -122.42436302145 37.8004143219856     0
3 -122.426995326766 37.8008726327692     0
4 -122.438737622757 37.7715411720578     0
5               abc            zsads     0

I have tried a number of the SO and other solutions, but the results do not seem to be working properly. Can anyone help?

Thanks!

Jack

like image 388
Jack Power Avatar asked May 13 '26 07:05

Jack Power


1 Answers

As a general note - your code is kind of weird. I would recommend either a for loop, or possibly better, a function that does this stuff. But you can make your loop work.

# A minimal working version
library(RJSONIO)
options(stringsAsFactors = FALSE)

# Create a data frame with the example data
geocode_area <- data.frame(X = c("-122.425891675136","-122.42436302145","-122.426995326766","-122.438737622757","abc"),
                           Y = c("37.7745985956747","37.8004143219856","37.8008726327692","37.7715411720578","zsads"),
                           Block = c(0,0,0,0,0))

# Your old function, unchanged
getUrl <- function(x,y) {

    root <- "http://geocoding.geo.census.gov/geocoder/geographies/coordinates?"
    u <- paste0(root,"x=", x,"&y=", y,"&benchmark=4&vintage=4&format=json")
    return(URLencode(u))
}

# Getting the length parameter
length <- nrow(geocode_area)
i <- 1
while(i <= length) {

    x_cord <- geocode_area$X[i]
    y_cord <- geocode_area$Y[i]
    target <- getUrl(x_cord,y_cord)

    # Here be new code
    # Do a try(), with silent = TRUE, which suppresses outputs to STDERR
    # In principle, this is dangerous - a better approach is to strip out the offending data before invoking it
    # Errors are, after all, there for a reason
    dat <- try(fromJSON(target),silent = TRUE)

    # Now, we conditionally complete the next steps
    # If the class of dat is not a try-error, perform your normal operations
    # Otherwise, bypass and print a note to the console
    if(class(dat) != "try-error") {

        geocode_area$Block[i] <- dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK
        print(paste(i/length*100,"% completed",sep=""))
        print(dat$result$geographies$`2010 Census Blocks`[[1]]$BLOCK)
    } else if (class(dat) == "try-error") {print("Error encountered, bypassing")}
i <- i + 1
}

EDITED TO ADD: Obviously, this uses try() instead of tryCatch(). However, as the poster ended up using try() and this may represent a different way to do it, I thought I'd leave it up.

like image 178
TARehman Avatar answered May 14 '26 21:05

TARehman