Day 5: Leaflet

The leaflet package lets you draw awesome interactive maps (using leaflet.js, I presume!), and it’s nicely documented on the RStudio website here. So I think that for today’s learning exercise I’ll follow along with the tutorial there, but maybe take a few excursions as I go. To make it a bit more fun I’ll use a different data set. A few moments on google turns up the latlong.net site, so I quickly grab data about the locations of a few places in Sydney from there, save it as a CSV, and my first task will be to plot them on a Sydney map. So here’s the data:

syd <- read.csv("https://djnavarro.net/files/latlong-sydney.csv")
syd
##          Place  Latitude Longitude
## 1  Opera House -33.85616  151.2153
## 2  Bondi Beach -33.89084  151.2743
## 3      Airport -33.94735  151.1794
## 4 Surrey Hills -33.89065  151.2129
## 5   Parramatta -33.80825  151.0050
## 6  Taronga Zoo -33.84105  151.2422
## 7    Bankstown -33.91729  151.0359

I am of course filled with many opinions about the choice of locations – I mean, Bondi, really? 🙄 The Inner Westie in me is appalled – but whatevs.

So let’s have a go at this. A quick browse through the tutorial suggests that I should try this for my first attempt:

sydneyMap <- leaflet() %>% 
             addTiles() %>%  
             addMarkers(
               lat = syd$Latitude, 
               lng = syd$Longitude, 
               popup = syd$Place
             )

If I’ve understood it right, this code is doing three things. First, the call to leaflet creates the map widget using the htmlwidgets package (which, hey, I should actually read the docs for that one too – but these are supposed to be quick posts and I’ve got a time budget). The widget is then piped to addTiles which uses data from Open Street Maps to draw the map itself. Finally the addMarkers function places map markers using the data from syd.

Here’s the map:

sydneyMap


That’s pretty awesome for a few minutes of googling and a cut-and-paste job!

Choosing different tiles

The map tiles in the widget shown above come from Open Street Map, which is a super cool thing in itself that I remember reading about one time ages ago. Apparently I can plug in tiles from many different providers though? That seems really neat - presumably I can get a very differnet look and feel just by tweaking that.

Looks like the addProviderTiles() function is the thing I need to do that. There’s a nice list of providers. So for instance if I wanted a black and white gothic looking thing, I could do this:

sydneyMap %>% addProviderTiles("Stamen.Toner")


Very cool! This is the kind of Sydney I can get behind!

Piping a data frame through the map layers

Okay, so now that I read a little further into the documentation 📚 I see that leaflet() and the various functions that provide map layers (e.g., addTiles(), addMarkers(), etc) all have an optional data argument which can be used to specify the data for the map. It seems pretty flexible. It can handle data frames (like the syd data frame I loaded earlier), but it also plays nicely with the sp package which (as I understand it) attempts to fold a lot of things about spatial mapping under a single framework. The cool thing is that the functions work pretty hard to guess how to use the variable names.

leaflet(data = syd) %>% addProviderTiles("Stamen.Watercolor") %>% addMarkers
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively


That’s neat. It didn’t work out that I wanted to use syd$Place as the popup labels for the markers, but I presume I could just manually set popup = syd$Place like last time.

Customising markers

Okay… moving right along! I’m on the clock here!

Apparently we can customise the markers? The default marker is fine, but it’s sometimes nice to come up with alternatives. There’s a “pirates and ships” icons example in the tutorial makes me wonder if I can do something like that with my Sydney map? A first pass at this:

Hm… skimming, skimming… ooooohhh the addAwesomeMarkers() function looks, well, awesome. It lets you specify markers using font-awesome and a bunch of other possibilities.

syd$icon_names <- c("font-awesome","bug","globe","coffee","paw","eye","plus")
icons <- makeAwesomeIcon(icon = syd$icon_names, library = "fa")
leaflet(data = syd) %>% addProviderTiles("Stamen.Watercolor") %>% 
  addAwesomeMarkers(icon = icons, popup = syd$Place)
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively


Very nice. I’m going to call that a victory!

Other examples?

Just before moving on completely, I took a little stickybeak at a few of the other ways you can use the widget. I could, for instance, plot a map that shows only the locations of various US cities as dots…

leaflet(maps::us.cities) %>% 
  addProviderTiles("Stamen.TonerLite") %>%
  addCircleMarkers(radius = 5, stroke = FALSE)
## Assuming "long" and "lat" are longitude and latitude, respectively


Along the same lines, if I actually knew what I were doing with leaflet, I could extend it to draw some very cool chloropleth maps. I feel like I need to get more of a sense of what’s going on here, but the tutorial has a very cute example:

path <- "https://djnavarro.net/files/us-states.geojson"
states <- geojsonio::geojson_read(x = path, what = "sp")

bins <- c(0, 10, 20, 50, 100, 200, 500, 1000, Inf)
pal <- colorBin("YlOrRd", domain = states$density, bins = bins)

labels <- sprintf(
  "<strong>%s</strong><br/>%g people / mi<sup>2</sup>",
  states$name, states$density
) %>% lapply(htmltools::HTML)

leaflet(states) %>%
  setView(-96, 37.8, 4) %>%
  addProviderTiles("Stamen.Watercolor") %>%
  addPolygons(
    fillColor = ~pal(density),
    weight = 2,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlight = highlightOptions(
      weight = 5,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE),
    label = labels,
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "15px",
      direction = "auto")) %>%
  addLegend(pal = pal, values = ~density, opacity = 0.7, title = NULL,
    position = "bottomright")


I mean, it’s not like I really have a need for any of this, but it’s so preeeeetttty!

Avatar
Danielle Navarro
Associate Professor of Cognitive Science

Related