rmapsdistancepostal-code

Getting distance between 2 UK Postcodes in R


I have a data frame df containing multiple observations with UK Postcode values. I want to create a new column which calculates the distance between the postcodes in df$origin and df$dest for each observation.

I haven't got funding for Google Maps API and was wondering if I can do this with PostcodeioR? Or is there an alternate free way of doing this in RStudio?

# MRE
origin <- c("S6 2PA", "S35 0DP", "M1 6BD", "DE55 4JF")
dest <- c("S5 7AU", "S5 7AU", "S5 7AU", "S5 7AU")

df <- tibble(origin,dest)

Preferably, the distance created would be the driving distance, rather than as the crow flies, however I appreciate this may not be possible.


Solution

  • The PoscodesioR package will look up your postcodes and tell you their longitude/latitude, so you can get the "crow-flies" distance using any of several methods such as geosphere::distHaversine

    library(tidyverse)
    library(PostcodesioR)
    library(geosphere)
    
    origin <- c("S6 2PA", "S35 0DP", "M1 6BD", "DE55 4JF")
    dest <- c("S5 7AU", "S5 7AU", "S5 7AU", "S5 7AU")
    
    df <- tibble(origin, dest)
    
    df %>%
      mutate(miles = map2(origin, dest, 
                             ~ distHaversine(postcode_lookup(.x)[,7:8],
                                             postcode_lookup(.y)[,7:8])/1609.34) |>
               unlist())
    #> # A tibble: 4 x 3
    #> origin   dest   distance
    #> <chr>    <chr>     <dbl>
    #> 1 S6 2PA   S5 7AU     1.98
    #> 2 S35 0DP  S5 7AU     4.63
    #> 3 M1 6BD   S5 7AU    32.5 
    #> 4 DE55 4JF S5 7AU    23.0 
    

    These all look pretty accurate on direct measurements.

    I'm not aware of a completely free API that allows measurement of driving distances. Getting a Google API key will allow you to get driving distances, and as far as I can tell you should be able to get about 40,000 measurements per month for free. You should be able to lookup and store the driving distance between all South Yorkshire postcodes and the Northern General Hospital over a two-month period free of charge. Depending on your project size, you may not need funding at all (though if you had to measure the driving distance between all 1.7 million UK postcodes and the Northern General Hospital then that would cost you about £7,000...).


    EDIT

    If you have a Google API key and billing set up, it may be just as easy to use the API directly. The following function will give you driving distances and times if you have registered your API key with ggmap

    driving_dist <- function(origins, destinations) {
      
      do.call("rbind",  Map(function(x, y) {
        
          res <- paste0("https://maps.googleapis.com/maps/api/distancematrix/json",
            "?destinations=", URLencode(x),
            "&origins=", URLencode(y),
            "&units=imperial",
            "&key=", ggmap::google_key()) |>
            httr::GET() |>
            httr::content() 
        
          data.frame(distance_metres = res$rows[[1]]$elements[[1]]$distance$value,
                     time_seconds = res$rows[[1]]$elements[[1]]$duration$value)
        }, origins, destinations)
      )
    }
    

    Testing, we have:

    df %>% mutate(driving_dist(origin, dest))
        # A tibble: 4 x 4
    #>    origin   dest   distance_metres time_seconds
    #>    <chr>    <chr>            <int>        <int>
    #>  1 S6 2PA   S5 7AU            5869          832
    #>  2 S35 0DP  S5 7AU           10145         1198
    #>  3 M1 6BD   S5 7AU           63816         4763
    #>  4 DE55 4JF S5 7AU           53346         2861