Introduction

This code-through will show how to take open data addresses and turn them into an interactive map using the Leaflet package. I will take addresses from the Phoenix Public Library system and plot these on a map, with markers that provide additional useful information about the libraries. The goal is to have a single page where people can go to find which library would be most useful to their needs. This map could also be embedded on the public library website to inform patrons.

Concept

This project built on information in a Towards Data Science Medium post by Brandon Walker.

Data

These maps were built using data from the Phoenix, AZ Open Data Portal. The data was not linked through the API (since it was broken at the time of creation) so the data is static as of 10/1/2020.

Ouchouch


The data provides us with a series of (semi-useful) headings:

ls(libraries)
##  [1] "AddressCity"  "AddressFull"  "AddressState" "AddressZip"   "DegreesX"    
##  [6] "DegreesY"     "Hours"        "OBJECTID"     "PlaceName"    "PlaceStatus" 
## [11] "PlaceType"    "PlaceWeb"     "X"            "Y"
head(libraries, n=5)
##           X        Y                   PlaceName         AddressFull
## 1 -112.0799 33.43590              Harmon Library      1325 S 5TH AVE
## 2 -112.0733 33.46252 Burton Barr Central Library  1221 N CENTRAL AVE
## 3 -111.9829 33.47868             Saguaro Library      2808 N 46TH ST
## 4 -112.0917 33.51986               Yucca Library     5648 N 15TH AVE
## 5 -112.0434 33.50595             Century Library 1750 E HIGHLAND AVE
##   AddressCity AddressState AddressZip PlaceType
## 1     PHOENIX           AZ      85003   LIBRARY
## 2     PHOENIX           AZ      85004   LIBRARY
## 3     PHOENIX           AZ      85008   LIBRARY
## 4     PHOENIX           AZ      85015   LIBRARY
## 5     PHOENIX           AZ      85016   LIBRARY
##                                                           PlaceWeb  DegreesX
## 1  http://www.phoenixpubliclibrary.org/Locations/Pages/Harmon.aspx -112.0799
## 2         http://www.phoenixpubliclibrary.org/Locations/BurtonBarr -112.0733
## 3 http://www.phoenixpubliclibrary.org/Locations/Pages/Saguaro.aspx -111.9829
## 4   http://www.phoenixpubliclibrary.org/Locations/Pages/Yucca.aspx -112.0917
## 5 http://www.phoenixpubliclibrary.org/Locations/Pages/Century.aspx -112.0434
##   DegreesY    Hours OBJECTID PlaceStatus
## 1 33.43590 8am-Noon       46    Curbside
## 2 33.46252 8am-Noon       54    Curbside
## 3 33.47868 8am-Noon      125    Curbside
## 4 33.51986 8am-Noon      160    Curbside
## 5 33.50595 8am-Noon      169    Curbside

The basic command to start a map in Leaflet simply requires you to addTiles() and then call the map:

m <- leaflet(libraries) %>%
  addTiles()   # Add default OpenStreetMap map tiles
  
m  # Print the map

But first we need to fix our data…


Preprocessing

We have two sets (4) of columns that correspond with longitude and latitude. I’m going to change those names to lng and lat to make it easier for Leaflet to read. This isn’t necessary but I thought it would be easier since we have another pair of columns that have the X/Y values as a backup if we needed that naming convention.

libraries <- libraries %>%
  rename(lng = DegreesX) %>%
  rename(lat = DegreesY)

The data from this portal is fairly minimal and requires very little preprosessing. For Leaflet to work properly, we need more than just the address of the library - which is provided in the dataframe under libraries$AddressFull.

Adding the Lon/Lat Coordinates


Geocoding with GGMAP

We have a series of addresses and X/Y coordinates that correspond with longitude and latitude. However, if you did not have lon/lat coordinates, you can load ggmap package and call the geocode() function to the addresses.

For example, if I wanted to find a central location in Phoenix, AZ as the center of my map (we’ll adjust the zoom later). I can chose the Burton Barr Library and pass the address through geocode() like this:

#geocode("1221 N. Central Ave, Phoenix, ArZ 85004")


Creating and Customizing Our Map

The purpose of this map is to show where all of the libraries are located, so we want to add markers. You can add basic blue markers by calling addMarkers() in Leaflet and then adding the lng/lat coordinates. You can also pass it through a dataframe if you have a list of coordinates. Calling addMarkers() will add markers for your points of interest.

libmap <- leaflet() %>%
  addTiles() %>%
  addMarkers(lng = libraries$lng, lat = libraries$lat)

libmap

Changing the Map Tiles

There are a huge number free, beautiful “tiles” (customized maps) that you can add to your interface - either as your base or on top of existing tiles. You can see examples on this equally beautiful GitHub page.. I chose the OpenStreetMap.HOT interface because it felt a little more subtle and emphasized traffic markings less.

libmap <- leaflet() %>%
  addProviderTiles(providers$OpenStreetMap.HOT) %>%
  addMarkers(lng = libraries$lng, lat = libraries$lat)

libmap

Adding Markers for the Libraries

I didn’t like how the large blue markers obscured data on the map so I made them into flat circles. I changed the open libraries to a green circle and I also added a circle that is red for the South Mountain Community Library because it is CLOSED.

libmap <- leaflet() %>%
  addProviderTiles(providers$OpenStreetMap.HOT) %>%
  addCircleMarkers(
    lng = libraries$lng, lat = libraries$lat, 
    radius = 6,
    color = "green",
    stroke = FALSE, fillOpacity = 0.5) %>%
  addCircleMarkers(
    lng = -112.0312464, lat = 33.38217769,
    radius = 6,
    color = "red",
    stroke = FALSE, fillOpacity = 0.6
  )
  
libmap


Adding Labels with Information

I would also like for the user to see the name of the library when they hover over the circles. Doing this only requires adding the label = libraries$PlaceName argument to the markers.

libmap <- leaflet() %>%
  addProviderTiles(providers$OpenStreetMap.HOT) %>%
  addCircleMarkers(
    lng = libraries$lng, lat = libraries$lat, 
    label = libraries$PlaceName,
    radius = 6,
    color = "green",
    stroke = FALSE, fillOpacity = 0.5) %>%
  addCircleMarkers(
    lng = -112.0312464, lat = 33.38217769, 
    label = libraries$PlaceName,
    radius = 6,
    color = "red",
    stroke = FALSE, fillOpacity = 0.5
  )
  
libmap


Clicking Popup Information

To make our map more useful, we’d like some basic information to popup when the user clicks on a marker. I’ve chosen the library’s website because I feel like that would lead the user to discovering all of the information that they need (from books to lending policies). This information is provided in the dataset so we can link to it using popup = libraries$PlaceWeb. This gets a little cluttered and so I might customize the boxes more in the future.

libmap <- leaflet() %>%
  addProviderTiles(providers$OpenStreetMap.HOT) %>%
  addCircleMarkers(
    lng = libraries$lng, lat = libraries$lat, 
    label = libraries$PlaceName,
    popup = libraries$PlaceWeb,
    radius = 6,
    color = "green",
    stroke = FALSE, fillOpacity = 0.5) %>%
  addCircleMarkers(
    lng = -112.0312464, lat = 33.38217769, 
    label = libraries$PlaceName,
    popup = libraries$PlaceWeb,
    radius = 6,
    color = "red",
    stroke = FALSE, fillOpacity = 0.5
  )
  
libmap

Final Product

 

A work by Sean Harrington

sean.harrington@asu.edu