After an interesting talk at the August EdinbR meeting, I wanted to try a bit of RMarkdown to document the process of making maps in Leaflet for R. Using data from the UK Lakes Portal, I ended up making a nice slippy map showing the varying depths of lochs in Assynt:

As with a lot of tutorials, I wanted to show the result first followed by how it can be achieved. The end of this guide shows how to do this in RMarkdown without repeating loads of code!

Adding Labels

To add labels to the lochs showing their name and mean depth, we can set up a list with a combination of HTML and our variable names and pass it to htmltools::HTML with lapply:

labels <- sprintf(
  "<strong>%s</strong><br/>Mean depth: %gm",
  lakes_l$NAME, lakes_l$MNDP
) %>% lapply(htmltools::HTML)


Centring / Zooming the Map

The leaflet library is quite inuitive, so it will automatically centre the map and set the zoom level based on (presumably) the bounds of your data. In this case, I wanted to zoom in one level further even though a small amount of data would be outside the map’s view. To do this, you can pass a zoom level to Leaflet’s setView function, but it requires a latitude and longitude for the map’s centre rather than being able to use the centre point it automatically set. I couldn’t find a way to get the centre point of a spatial data frame, but we can get the bounding box using sf’s st_bbox and compute the centre thusly:

latitude <- as.numeric((st_bbox(lakes_l)["ymin"]+st_bbox(lakes_l)["ymax"])/2)
longitude <- as.numeric((st_bbox(lakes_l)["xmin"]+st_bbox(lakes_l)["xmax"])/2)


Leaflet Chloropleth

To categoprise the data, we first need to set up some bins for the data and define a suitable colour scheme. We’re using data from Mean Depth (MNDP) here:

bins <- c(0, 2, 4, 6, 8, 10, 15, 20, Inf)
pal <- colorBin("Blues", domain = lakes_l$MNDP, bins = bins)

Then we can create our leaflet map using the following code, styling the data based on this tutorial on chloropleth maps:

map1 <- leaflet(lakes_l, width = "100%") %>%
  setView(lat=latitude, lng=longitude, zoom=11) %>%
  addProviderTiles(providers$Stamen.TonerLite) %>%
  addPolygons(fillColor = ~pal(MNDP),
    weight = 0.2,
    opacity = 1,
    color = "black",
    fillOpacity = 1,
    highlight = highlightOptions(
      weight = 1,
      color = "black",
      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 = ~MNDP, opacity = 0.7, title = "Mean depth (m)", position = "bottomright")


Alternative Maps

Once we’ve set up one map, it’s really easy to use the same data and present a different variable. Here’s a map of Shoreline Development Index (SDI, showing how complex the loch’s shape is) with a different zoom level:


RMarkdown - Chunk Referencing

When writing this documentation, I wanted to show the output from chunks of code then later show the code itself, ideally without repeating the code in the script. This can be done by first naming a code chunk, then referncing it by name later on with different parameters. Here I am showing the code from the chunk named ‘leaf’ without re-running it:

```{r echo=TRUE, eval=FALSE}
<<leaf>>
```