rgoogle-mapslatitude-longitudegoogleway

How to find nearest road to single pair of latitude/longitude coordinates using R?


I have a list of a couple of hundred latitude-longitude coordinate pairs for different locations. My goal is to obtain an estimate of the driving duration from a 'home' location to each of the coordinate pairs, using R.

I have had some success using the googleway package in R, but have (predictably) run into problems for locations which are far from a road, e.g. if the coordinates are for a mountain top. In these instances I would like to estimate instead the driving times to the nearest road to each problematic coordinate pair.

To illustrate, let's say my home location is;

home <- "Edinburgh, UK"

...and an example dataframe of locations I want to find driving times to could be;

location <- c("place_a", "place_b", "place_c") 
latitude <- c("56.87034", "57.69380", "57.36243")
longitude <- c("-4.199001", "-5.128715", "-5.104728")

df <- data.frame(location, latitude, longitude) 

I can obtain distance/duration, etc., between home and place_a, and between home and place_b using something like;

(NB. You'll need your own Google Maps api key to replicate this section... )

library(googleway)
api_key <- [insert your Google Maps api key here!]

results <- google_distance(origins = home,
                  destinations = list(c("56.87034,-4.199001"),
                                      ("57.69380,-5.128715")),
                  mode = "driving",
                  key = api_key,
                  units = "imperial")

I get all the data I want using:

results$rows[[1]]

We run into trouble however when trying the same for the coordinates for place_c, which returns ZERO_RESULTS;

results2 <- google_distance(origins = home,
              destinations = ("57.36243,-5.104728"),
              mode = "driving",
              key = api_key,
              units = "imperial")

Here I think the issue is that the coordinates are for half-way up a mountain, so in this case I want to find the nearest road to the coordinates instead. I'd hoped to have some luck with the nearest_road function of googleway but cannot seem to get it working, e.g something like this doesn't work;

df_points <- read.table(text = "lat lon
                     57.36243 -5.104728", header = T)

nearest_road <- google_nearestRoads(df_points, key = api_key)

Can anyone advise what the problem is here? Or suggest a better solution altogether?!

Many thanks.


Solution

  • I am working on this very problem in a package that will be available on github soon (called spaceheater). In the meantime:

    I would download the Open Street Maps shapefile from geofabrik for the country you are working with. For example Nigeria: http://download.geofabrik.de/africa/nigeria.html

    EDITED WITH THE SUGGESTIONS OF monkeytennis(thanks!):

    library(sp)
    library(rgdal)
    library(raster)
    library(googleway)
    library(geosphere)
    library(foreach)
    ###I did Nigeria because I have it in my file downloaded, you would use UK###
    roadshp <- readOGR(dsn="nigeria-latest-free.shp", 
    layer="gis.osm_roads_free_1")
    #Isolate primary roads (or secondary and tertiary) if you wish#
    roads <- roadshp[roadshp$fclass %in% c("primary", "secondary", "tertiary"),]
    #Use SpatialPoints for your gps coords
    location <- c("place_a", "place_b", "place_c")
    latitude <- c(8.641, 10.892, 11.797)
    longitude <- c(6.0046, 11.146, 5.477)
    df <- data.frame(location, latitude, longitude)
    coordinates(df)=~longitude+latitude
    sp1 <- SpatialPoints(df)
    proj4string(sp1)=CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84
                     +towgs84=0,0,0")
    clodist <- dist2Line(sp1, roads)
    df <- as.data.frame(df)
    df$clodist <- clodist[,c("distance")]
    df$lat <- clodist[,c("lat")]
    df$lon <- clodist[,c("lon")]
    iters <- nrow(df)
    origin <- as.character("9.056, 7.497")
    gc1 <- data.frame(round(df[,c("lat")],3), round(df[,c("lon")],3))
    colnames(gc1) <- c("lat","lon")
    df$lat <- as.character(gc1$lat)
    df$lon <- as.character(gc1$lon)
    gt2 <- paste(df[,c("lat")], df[,c("lon")], sep=",")
    results <- google_distance(origins =origin, destinations= gt2,
                mode="driving",
                key="Your API Key Here")
    results <-unlist(results)
    results <- as.data.frame(results)
    ttt <- head(results,-1)
    ttt <- ttt[-c(iters+1), ]
    m1 <- matrix(ttt, ncol=iters, byrow=TRUE)
    distance <- as.data.frame(m1)
    rownames(distance) <- c("Address", "DistanceKM", 
    "DistanceM","TimeTextLow","TimeSecondsLow","TimeTextHigh","TimeSecondsHigh", 
    "Status")