ropensci / PostcodesioR

API wrapper around postcodes.io - free UK postcode lookup and geocoder
https://docs.ropensci.org/PostcodesioR
39 stars 7 forks source link

postcode_lookup failing unexpectedly #11

Closed MikeJohnPage closed 4 years ago

MikeJohnPage commented 4 years ago

For some postcodes, I think the postcode_lookup() function is failing in (what I think) is an unexpected way.

Take the postcode "IM26BG" as an example. The postcode appears to be valid:

PostcodesioR::postcode_validation("IM26BG")
#> [1] TRUE

However, the postcode_lookup function fails in R:

PostcodesioR::postcode_lookup("IM26BG")
#> Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, : arguments imply differing number of rows: 1, 0

Passing the postcode into the 'Lookup a postcode' API endpoint on the official postcodes.io site reveals that this postcode returns null in many of the fields:

{
    "status": 200,
    "result": {
        "postcode": "IM2 6BG",
        "quality": 9,
        "eastings": null,
        "northings": null,
        "country": "Isle of Man",
        "nhs_ha": "Isle of Man",
        "longitude": null,
        "latitude": null,
        "european_electoral_region": null,
        "primary_care_trust": "Isle of Man",
        "region": null,
        "lsoa": null,
        "msoa": null,
        "incode": "6BG",
        "outcode": "IM2",
        "parliamentary_constituency": null,
        "admin_district": null,
        "parish": null,
        "admin_county": null,
        "admin_ward": null,
        "ced": null,
        "ccg": "Isle of Man",
        "nuts": null,
        "codes": {
            "admin_district": "M99999999",
            "admin_county": "M99999999",
            "admin_ward": "M99999999",
            "parish": "M99999999",
            "parliamentary_constituency": "M99999999",
            "ccg": "M01000001",
            "ccg_id": "YK1",
            "ced": "M99999999",
            "nuts": null
        }
    }
}

I believe this explains the R error, as it appears the lookup_postcode() function is failing when it finds null values (creating differing number of rows).

I think the lookup_postcode() function should convert null values to NA or fail with a more informative error message.

erykwalczak commented 4 years ago

Thanks for spotting this issue. I will work on it over the weekend. Feel free to send a PR if you managed to fix it yourself.

erykwalczak commented 4 years ago

Are you using CRAN or GitHub version? There are still some changes that haven't been pushed to CRAN so the dev (GitHub) version is the latest. I don't get the error that you mentioned when running PostcodesioR::postcode_lookup("IM26BG") This line works for me as expected using the dev version. Was that the only postcode that caused errors? Did you hit the query limit (postcodes.io limits the number of calls)?

MikeJohnPage commented 4 years ago

In response to your questions:

Solution with CRAN version

In case you are interested I solved the problem by using a combination of functions from {purrr} to ignore errors:

# Load libraries
library(tidyverse)
library(PostcodesioR)

# Create vector of postcodes
postcodes <- c("TEST123", "TEST456", "TEST789")

# Geocoding function to check if postcode is valid, and if so, return lat/lng,
# else silently ignore
geocode <- function(postcode){
  if(postcode_validation(postcode)){
    p <- postcode_lookup(postcode)
    tibble(postcode = postcode,
           latitude = purrr::pluck(p, "latitude"),
           longitude = purrr::pluck(p, "longitude"))
  }
}

# Handle errors safely
safe_geo <- safely(geocode)

# Return lat/lng coords
coords <- map(postcodes, safe_geo) %>% 
  transpose() %>% 
  use_series("result") %>% 
  bind_rows()

Dev version

I updated to the GitHub dev version and indeed it no longer throws an error for the same postcode. Thanks for the update 👍