Today we’re going to use the googleway R package, which allows their user to do requests to the GoogleMaps Places API. The goal is to create maps of specific places (restaurants, museums, etc.) with information from Google Maps rankings (number of stars given by other people). I already discussed this in french here to rank swimming pools in Paris. Let’s start by loading the three libraries I’m going to use : googleway, leaflet to create animated maps, and RColorBrewer for color ranges.
library(googleway) library(leaflet) library(RColorBrewer)
First things first. To do API request to Google, we need an API key ; you can ask for one here. We’ll use this key for the rest of the program, so let’s declare a global variable :
api_key <- "YourKeyHereIWontGiveYouMine"
Retrieving Google Data
We’re going to use the google_places function to get a list of places matching a description, called research in my program (for instance : “Restaurant, Paris, France”). The output are multiple, and I’m going to store the place ID and the rating. I’ll also store the research token ; that’ll be explained later.
gmaps_request <- google_places(search_string = research, language = language, key = api_key) gmaps_data <- gmaps_request$results place_id <- gmaps_data$place_id rating <- gmaps_data$rating token <- gmaps_request$next_page_token
This function returns up to 20 places associated to the research by Google. If you want more than 20, you need to use the token previously stored in order to ask the Google Places API to give you the next results, by tweaking the function this way :
gmaps_request <- google_places(search_string = research, language = language, key = api_key, page_token = token)
There are tow caveats to this function. Firstly, the token can be NULL. In this case, there isn’t any further research results you can get. This happens automatically as soon as you reach 60 results. Secondly, the API needs time to refresh the token research (see here) ; that’s why we’re going to make R wait a few seconds, using Sys.sleep(time) between our requests. Our complete function is therefore :
gmaps_request <- google_places(search_string = research, language = language, key = api_key) gmaps_data <- gmaps_request$results place_id <- gmaps_data$place_id rating <- gmaps_data$rating token <- gmaps_request$next_page_token Sys.sleep(5) continue <- TRUE while (continue) { gmaps_request <- google_places(search_string = research, language = language, key = api_key, page_token = token) gmaps_data <- gmaps_request$results if (!is.null(gmaps_request$next_page_token)) { place_id = c(place_id,gmaps_data$place_id) rating = c(rating,gmaps_data$rating) token <- gmaps_request$next_page_token Sys.sleep(5) } else{continue <- FALSE} }
Now we’re going to search for the spatial coordinates of the places we found. To this extent, we’re going to use the google_place_details function of the packages, and retrieve latitude and longitude with these two functions :
get_lat <- function(id, key, language) { id <- as.character(id) details <- google_place_details(id, language = language, key=key) return(details$result$geometry$location$lat) } get_lng <- function(id, key, language) { id <- as.character(id) details <- google_place_details(id, language = language, key=key) return(details$result$geometry$location$lng) }
All these blocks add up to build the complete function :
get_gmaps_data <- function(research, api_key, language) { gmaps_request <- google_places(search_string = research, language = language, key = api_key) gmaps_data <- gmaps_request$results place_id <- gmaps_data$place_id rating <- gmaps_data$rating token <- gmaps_request$next_page_token Sys.sleep(5) continue <- TRUE while (continue) { gmaps_request <- google_places(search_string = research, language = language, key = api_key, page_token = token) gmaps_data <- gmaps_request$results if (!is.null(gmaps_request$next_page_token)) { place_id <- c(place_id, gmaps_data$place_id) rating <- c(rating, gmaps_data$rating) token <- gmaps_request$next_page_token Sys.sleep(5) } else{continue <- FALSE} } lat = sapply(place_id, get_lat, key=api_key, language=language) lng = sapply(place_id, get_lng, key=api_key, language=language) return(data.frame(place_id, rating, lat, lng)) }
Map plot
The next part is more classical. We’re going to order the ratings of the data frame built by the previous function in order to arrange the places in differents groups. Each of the groups will be associated to a color on the data plot. If we want to make number_colors groups with the color scheme color (for instance, “Greens”), we are using the following instructions :
color_pal <- brewer.pal(number_colors, color) pal <- colorFactor(color_pal, domain = seq(1,number_colors)) plot_data <- gmaps_data plot_data$ranking <- ceiling(order(gmaps_data$rating)*number_colors/nrow(plot_data))
The definitive function just needs the addition of the leaflet call :
show_map <- function(number_colors, gmaps_data, color="Greens") { color_pal <- brewer.pal(number_colors,color) pal <- colorFactor(color_pal, domain = seq(1,number_colors)) plot_data <- gmaps_data plot_data$ranking <- ceiling(order(gmaps_data$rating)*number_colors/nrow(plot_data)) leaflet(plot_data) %>% addTiles() %>% addCircleMarkers( radius = 6, fillColor = ~pal(ranking), stroke = FALSE, fillOpacity = 1 ) %>% addProviderTiles(providers$CartoDB.Positron) }
Examples
I just need to combine these two functions in one, and then to do some food-related examples !
maps_ranking_from_gmaps <- function(research, api_key, language, number_colors=5, color="Greens") { show_map(number_colors, get_gmaps_data(research, api_key, language), color) } maps_ranking_from_gmaps("Macaron, Paris, France", api_key, "fr") maps_ranking_from_gmaps("Macaron, Montreal, Canada", api_key, "fr") maps_ranking_from_gmaps("Poutine, Montreal, Canada", api_key, "fr", 5, "Blues") maps_ranking_from_gmaps("Poutine, Paris, France", api_key, "fr", 5, "Blues")
which returns the following maps :
Macaron in Paris, France
Macaron in Montreal, Canada
Poutine in Montreal, Canada
Poutine in Paris, France (I guess French people are not ready for this)