They say if you are asked something once, just respond via email, but if you get asked twice, then blog about it. I’m taking that approach with this one by showing how to get times and distances using the Google Maps API for both
R and
Python (if you’re looking for the
Python version, you can find it
here).
I’ve had to help provide drive distances and times on numerous occasions, often provided in a large Excel file of cities and countries or postal codes. Clearly, nobody wants to go about placing each item into Google Maps and then entering that value back into their spreadsheet. Who has time for that?
Typically, this comes in the form of a bunch of cities or postal codes to get distances to and from, so let’s put a data frame together with these pairs.
library(knitr)
locations = data.frame(origin_city = c("Hamburg", "Toronto", "Sucre",
"Jaipur", "Wellington"),
origin_country = c("Germany", "Canada", "Bolivia",
"India", "New Zealand"),
destination_city = c("Zurich", "New York", "Santiago",
"Bengaluru", "Auckland"),
destination_country = c("Switzerland", "USA", "Chile",
"India", "New Zealand"))
kable(locations, "markdown", align = "l")
| Hamburg |
Germany |
Zurich |
Switzerland |
| Toronto |
Canada |
New York |
USA |
| Sucre |
Bolivia |
Santiago |
Chile |
| Jaipur |
India |
Bengaluru |
India |
| Wellington |
New Zealand |
Auckland |
New Zealand |
In my opinion, the best package to use for this is
gmapsdistance. Just like for
Python's package, you can get an API key to
here. Unlike the
Python version, I’ve actually found that the key isn’t always necessary for whatever reason. Keep in mind that you only have
2,500 free calls to the API per day. So if you have additional distances to calculate, then consider paying for it, or spreading your load across multiple days (or get a friend’s key, whatever works).
library(gmapsdistance)
key <- "Your Key Here!"
We’ll need to do one thing to our data, and that’s combine the city and country names with ‘+’ and fill in any blanks.
origin <- gsub(" ", "+",
paste(
locations$origin_city, locations$origin_country,
sep = "+"))
destination <- gsub(" ", "+",
paste(
locations$destination_city, locations$destination_country,
sep = "+"))
locs <- data.frame(origin, destination)
kable(locs, "markdown", align = "l")
| Hamburg+Germany |
Zurich+Switzerland |
| Toronto+Canada |
New+York+USA |
| Sucre+Bolivia |
Santiago+Chile |
| Jaipur+India |
Bengaluru+India |
| Wellington+New+Zealand |
Auckland+New+Zealand |
With the data ready, we’re set to send it to the Google Maps API. Implementation of this is incredibly straightforward and easy to use. You could simply call it and apply it to the vectors in the data frame, but you’d get values for each city combination, and not all of them have driving distances between them considering many are on different continents. Plus, that may not always be necessary and you have a limited number of calls to the API you can make anyway. So it’s better to be wise about how you use them.
You’ll notice too, that the result is a list of three, which gives the estimated time it takes, distance, and status (i.e. whether a route exists or not). If you want any one of these in particular, you can extract them by indexing the list or using
$Time,
$Distance,
$Status.
results <- t(mapply(function(x, y) gmapsdistance(origin = x,
destination = y,
mode = "driving"),
locs$origin, locs$destination))
rownames(results) <- NULL
locations <- cbind(locations, results)
kable(locations, "markdown", align = "l")
| Hamburg |
Germany |
Zurich |
Switzerland |
30143 |
865780 |
OK |
| Toronto |
Canada |
New York |
USA |
28028 |
789792 |
OK |
| Sucre |
Bolivia |
Santiago |
Chile |
99951 |
2318802 |
OK |
| Jaipur |
India |
Bengaluru |
India |
117000 |
2001939 |
OK |
| Wellington |
New Zealand |
Auckland |
New Zealand |
28403 |
642828 |
OK |
The time is given in minutes and the distances are in meters by default, so convert those units however you like. Overall, great and easy package to use!