rgeocodingtigris

Cannot GeoCode with Tigris


I'm trying to generate census tracts geoids for a batch of addresses. When I use the "append_geoid" function in the tigris package, r returns "Error in call_geolocator(as.character(address$street[i]), as.character(address$city[i]), : Bad Request (HTTP 400)".

I used the example data given in the r documentation and it produced the same result. Code below. Any help on how to solve the issue is appreciated!

airports <- dplyr::data_frame(street = "700 Catalina Dr", city = "Daytona Beach", state = "FL")

append_geoid(airports, 'tr) # Populate Census Tract GEOID

Solution

  • EDIT: A fixed version of the package is on github:

    remotes::install_github("walkerke/tigris")
    

    Then try again

    EDIT 2:

    The version on github still seems to give errors, though different ones this time. The HTTP call succeeds, but the response doesn't contain what his function expects it to. I'd contact him or her.

    My Initial Post:

    I got the same message as you do.

    I did: debug( call_geolocator )

    And ran it again, this time stepping through it. After a few code lines it creates the url: https://geocoding.geo.census.gov/geocoder/geographies/address?street=700%20Catalina%20Dr&city=Daytona%20Beach&state=FL&benchmark=Public_AR_Census2010&vintage=Census2010_Census2010&layers=14&format=json

    This url then fails. Opening this url in a browser also gives an error, saying invalid benchmark.

    At this point it's about time to call the author and make him aware that his package is not working any more.

    For reference, this is what the debug session looked like in my terminal, until I inspected the full url created and hit Q to stop debuging:

    > debug( call_geolocator )
    > append_geoid(airports, 'tract') # Populate Census Tract GEOID
    debugging in: call_geolocator(as.character(address$street[i]), as.character(address$city[i]), 
        as.character(address$state[i]))
    debug: {
        call_start <- "https://geocoding.geo.census.gov/geocoder/geographies/address?"
        if (is.na(zip)) {
            url <- paste0("street=", utils::URLencode(street), "&city=", 
                utils::URLencode(city), "&state=", state)
        }
        if (!is.na(zip)) {
            if (class(zip) == "character" & nchar(zip) == 5 & !grepl("\\D", 
                zip)) {
                url <- paste0("street=", utils::URLencode(street), 
                    "&city=", utils::URLencode(city), "&state=", 
                    state, "&zip=", zip)
            }
            else {
                message("'zip' (", paste0(zip), ") was not a 5-character-long string composed of :digits:. Using only street, city, state.")
                url <- paste0("street=", utils::URLencode(street), 
                    "&city=", utils::URLencode(city), "&state=", 
                    state)
            }
        }
        call_end <- "&benchmark=Public_AR_Census2010&vintage=Census2010_Census2010&layers=14&format=json"
        url_full <- paste0(call_start, url, call_end)
        r <- httr::GET(url_full)
        httr::stop_for_status(r)
        response <- httr::content(r)
        if (length(response$result$addressMatches) == 0) {
            message(paste0("Address (", street, " ", city, " ", state, 
                ") returned no address matches. An NA was returned."))
            return(NA_character_)
        }
        else {
            if (length(response$result$addressMatches) > 1) {
                message(paste0("Address (", street, " ", city, " ", 
                    state, ") returned more than one address match. The first match was returned."))
            }
            return(response$result$addressMatches[[1]]$geographies$`Census Blocks`[[1]]$GEOID)
        }
    }
    Browse[2]> 
    debug: call_start <- "https://geocoding.geo.census.gov/geocoder/geographies/address?"
    Browse[2]> 
    debug: if (is.na(zip)) {
        url <- paste0("street=", utils::URLencode(street), "&city=", 
            utils::URLencode(city), "&state=", state)
    }
    Browse[2]> 
    debug: url <- paste0("street=", utils::URLencode(street), "&city=", 
        utils::URLencode(city), "&state=", state)
    Browse[2]> 
    debug: if (!is.na(zip)) {
        if (class(zip) == "character" & nchar(zip) == 5 & !grepl("\\D", 
            zip)) {
            url <- paste0("street=", utils::URLencode(street), "&city=", 
                utils::URLencode(city), "&state=", state, "&zip=", 
                zip)
        }
        else {
            message("'zip' (", paste0(zip), ") was not a 5-character-long string composed of :digits:. Using only street, city, state.")
            url <- paste0("street=", utils::URLencode(street), "&city=", 
                utils::URLencode(city), "&state=", state)
        }
    }
    Browse[2]> 
    debug: call_end <- "&benchmark=Public_AR_Census2010&vintage=Census2010_Census2010&layers=14&format=json"
    Browse[2]> 
    debug: url_full <- paste0(call_start, url, call_end)
    Browse[2]> 
    debug: r <- httr::GET(url_full)
    Browse[2]> url_full
    [1] "https://geocoding.geo.census.gov/geocoder/geographies/address?street=700%20Catalina%20Dr&city=Daytona%20Beach&state=FL&benchmark=Public_AR_Census2010&vintage=Census2010_Census2010&layers=14&format=json"
    Browse[2]> Q
    

    Going to the human interface of this: https://geocoding.geo.census.gov/geocoder/locations/address?form

    It does indeed look like the benchmark in that url above is no longer an available in the dropdown select box. Changing it to Public_AR_Census2020 instead gives another error, Invalid vintage in request. Changing 2010 to 2020 in that string results in a successfull HTTP request: https://geocoding.geo.census.gov/geocoder/geographies/address?street=700%20Catalina%20Dr&city=Daytona%20Beach&state=FL&benchmark=Public_AR_Census2020&vintage=Census2010_Census2010&layers=14&format=json .

    This doesn't really help you much at this point, but at least you can contact the author with an indication that the problem can be solved and you could give him some info to start working with.

    If you're savy, you could clone his package source and fix it yourself, offer the fix to him, but nevertheless use your own fixed package until he gets around.