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.
This project built on information in a Towards Data Science Medium post by Brandon Walker.
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.
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…
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.
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")
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
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
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
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
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
A work by Sean Harrington
sean.harrington@asu.edu