Posted on
Screenshot of Dashboard

Screenshot of Dashboard


Introduction


In this post, we will take a look at the city of Hamburg and discover what the city has to offer. We will make use of the Google Places API so that we can extract information like geographic, rating, contact, etc. This is a great way to discover new places in the city that you live in. I have lived in Hamburg for nearly 2 years now, and there are still so many places that I have yet to visit.

Click Here to See the Live Dashboard. If you liked the dashboard that I built, follow along and I will show how I to build the interactive map.



Data Preparation


Required Packages

# Load packages
library(tidyverse)
library(rjson)
library(leaflet)
library(htmltools)
library(htmlwidgets)


Retrieve API

In order to gather the data for Hamburg, we are going to need to get an API key from the Google API Console. Once you are there, you will need to start a new project and use the Google Places API Web Service for the project.

Google Places: make your app stand out with detailed information about 100 million places across a wide range of categories, from the same database as Google Maps and Google+. Thus, with this API we will be able to extract valuable information such as geodata, rating, and contact information.

# Replace with your API key 
apikey = "YOUR_KEY"


Import Data

Google Places searches has two main components the type, which is limited by a set, and the keyword which is optional and makes the query’s scope narrower.

I am going to show you how I made the map at the top of the page which shows different options you have when you are out at night in Hamburg.

Here we are going to build up a data frame that first states the types and keyword pairs that we want to search.

search <- tibble(
  type = c("bar", "restaurant", "night_club"),
  keyword = c("bar", "kebab", "club")
)

Now we are going to create a new variable query which will be used to call the API. The basics of the query call can be found here. However, you should note that we are calling to get json output back, and we are looking for are respective types and keywords from the center of Hamburg (given by the location coordinates) with a radius of 6000 meters.

search <- search %>%
  mutate(
    query = paste0(
      "https://maps.googleapis.com/maps/api/place/radarsearch/json?",
      "location=53.5666,9.9846&radius=6000&type=",
      type, "&keyword=",
      keyword, "&key=", 
      apikey, sep = ""
      )
    )
search$query
## [1] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=53.5666,9.9846&radius=6000&type=bar&keyword=bar&key=YOUR_KEY"         
## [2] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=53.5666,9.9846&radius=6000&type=restaurant&keyword=kebab&key=YOUR_KEY"
## [3] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=53.5666,9.9846&radius=6000&type=night_club&keyword=club&key=YOUR_KEY"

Now that we have the proper queries ready it is time to actually call the API which will give us JSON structured data of the bars, clubs, and kebab shops in Hamburg.

We are going to make use of the purrr and the rjson packages and map over each search$query using the fromJSON() command to read the information into R.

# Call each query into a list of 3 JSON outputs
jsons <- search$query %>% 
  map(~ fromJSON(paste(readLines(.x), collapse="")))

# Separate the 3 JSONs into respective queries
bar.json <- jsons[[1]]$results
kebab.json <- jsons[[2]]$results
club.json <- jsons[[3]]$results


Extract & Manipulate Data

Now that we have each JSON output in individual variables have a look to get a feel for the structure of the output. JSON output is not the easiest to analyze in R, but luckily with the help of the purrr package it is easy to extract the information that we need.

Let’s check out how we will extract the place_id and geocodes. You should also notice that we don’t have the name of each location, but rather this uninformative place_id variable which we will have to use later to extract information like name, rating, and url from the url later.

# Manipulate JSON data from "bar" query
# Extract place ID
placeID <- bar.json %>% 
  map_chr("place_id")

# Extract latitude
lat <- bar.json %>% 
  map("geometry") %>% 
  map("location") %>% 
  map_dbl("lat")

# Extract longitude
lng <- bar.json %>% 
  map("geometry") %>% 
  map("location") %>% 
  map_dbl("lng")

# Create Data Frame for bar
df.bar <- tibble(
  placeID = placeID,
  lat = lat,
  lng = lng
) %>% 
  mutate(
    type = "bar",
    keyword = "bar"
  )

You will need to repeat these steps for the other two JSON variables clubs and kebabs. Eventually creating data frames for the two of them and combining them with each other into a data frame named df.

# Combine the three data frames into one
df <- bind_rows(df.bar, df.kebab, df.club)

We are able to now plot each place_id on the map, but that doesn’t really help us because we don’t know anything about each location. Therefore, we are going to need to call the API again and ask for more details for each place_id.

# Add query to pass to API
df <- df %>% 
  mutate(
    query = paste0(
      "https://maps.googleapis.com/maps/api/place/details/json?placeid=",
      placeID, "&key=",
      apikey, sep = ""
    )
  )

Similar to how we extracted place_id and geolocation before, we are going to extract the name, rating, url, and phone number from each of the locations that we have already collected. Once again we are using the purrr package in order to map and extract the desired information from the JSON output.

# Extract name
name <- json.place %>% 
  map("result") %>% 
  map_chr("name")

# Extract rating
rating <- json.place %>% 
  map("result") %>% 
  map("rating") %>% 
  map_dbl(~ifelse(is_empty(.), 0, as.numeric(round(.,1))))
  
# Extract website
url <- json.place %>% 
  map("result") %>% 
  map("website") %>% 
  map_chr(~ifelse(is_empty(.), "No Website", .))

# Extract phone number
number <- json.place %>% 
  map("result") %>% 
  map("international_phone_number") %>% 
  map_chr(~ifelse(is_empty(.), "No #", .))

Now that all the desired information is gathered let’s bind the new columns to our original data frame and select only the information that we wish to keep.

df <- bind_cols(df,
    name = name, 
    number = number, 
    url = url,
    rating = rating
  ) %>% 
  select(
    name, number, url,
    rating, type, keyword,
    lat, lng
    )

The data is almost ready for plotting, but before we do that, let’s add another variable that we will join with df called Category, which will look nicer and be more informative in our output as opposed to keyword or type.

# Add Category column
cats <- c("Bar", "Döner", "Club")

# Create data frame
categories <- tibble(
  keyword = keyword,
  Category = cats
)

# Join categories to df
df <- df %>% 
  left_join(categories)



Visualize Data


We want to color code the points on the map, so let’s create a color palette for the different categories.

type.factor <- colorFactor(
  c("red", "purple", "yellow"),
  domain = c("Bar","Club", "Döner")
)

Now we will create a HTML output for the hovertext information that will display over each point of our Leaflet() plot.

# HTML to be inserted into Leaflet plot (labels)
hovertext <- mapply(
  function(name, rating, number, url) {
    htmltools::HTML(
      sprintf(
        "<div style='font-size:12px;width:200px;float:left'>
        <span style='color:#221e1e;font-size:15px;font-weight:bold'>%s</span><br/>
        <span style='color:#5a5a5a;font-size:12px'>Rating: <em>%s</em></span><br/>
        <span style='color:#5a5a5a;font-size:12px'><em>%s</em></span><br/>
        <span style='color:#5a5a5a;font-size:12px'><em>%s</em></span>
        </div>",
        htmlEscape(name), htmlEscape(rating), htmlEscape(number), htmlEscape(url)
      )
    )
  },
  factor(df$name), df$rating, df$number, df$url,
  SIMPLIFY = F
)

Lastly I will show you how to create the leaflet map that you saw at the beginning of the project and we will name it map.

map <- df %>% 
  leaflet() %>%
  # Add the coordinates for the center of Hamburg
  setView(lng = 9.9856, lat = 53.5566, zoom = 14) %>% 
  # This gives us the black map output
  addProviderTiles(providers$CartoDB.DarkMatter) %>%
  addCircleMarkers(
    lng = ~lng, 
    lat = ~lat,
    # Here we pass our colour palette
    color = ~type.factor(Category),
    fillOpacity = 0.6,
    # Here we pass our hovertext HTML
    label = hovertext,
    radius = 6,
    labelOptions = labelOptions(
      offset = c(-80,-110),
      direction='bottom',
      textOnly = T,
      style=list(
        'background'='rgba(255,255,255,0.95)',
        'border-color' = 'rgba(0,0,0,1)',
        'border-style' = 'solid',
        'border-width' = '4px'))
  ) %>% 
  # Here we add a legend with our color palette
  addLegend(
    pal = type.factor,
    values = ~Category,
    opacity = 1
  )



Conclusion


Google APIs can be a great source of information that you can use to create interactive plots with the help of R and JavaScript libraries such as Leaflet. I hope this post helped you learn a bit about data collection, manipulation, visualization in addition to handling JSON.

If you are curious as to how I created the dashboard, take a look at the source code that can be found in the top-right corner.



Acknowledgments



comments powered by Disqus