Postcode Polygons on a Leaflet Map - Updated

November 21, 2020    leaflet sf

Following an earlier post where I plotted postcode polygons on a Leaflet map I wanted to update it to use the sf package which is now my default package for working with spatial data. Note that I’ve also started using <- again after being a longtime user of =.

Sorting the Data

First we’ll load the packages we need.


Next we read in the data. The file has two layers of polygons and we need to specify which one we want. I have chosen to work with the postcode district which is the first half of our postcodes.

postcodes <- st_read("postcode_polygons.gpkg", layer = "postcode_district")
Simple feature collection with 7077 features and 2 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: 5720 ymin: 5180 xmax: 655503 ymax: 1220373
projected CRS:  Transverse Mercator

This gives us a tidy version of our earlier data and the message provided when reading it in shows us our CRS which we’re going to have to change from Transverse Mercator to something that will work with Leaflet - latitude and longitude. We can do this using st_transform()

postcodes <- st_transform(postcodes, 4326)

We can now check that we have lat and long.

[1] TRUE

Plotting the Ploygons

To simplify plotting things (and reduce the amount of data needed for the leaflet map) we can select just those postcode districts starting IV. The sf package allows us to use tidyverse functions, which are my preferred options anyway.

postcodes <- filter(postcodes, str_detect(pc_district, "IV"))

Now we can construct a map

leaflet(postcodes, width = "100%") %>% 
  setView(lng = -3.64, lat = 58, zoom = 7) %>%
  addTiles() %>% 

To get a little more info we can add the postcode district as a popup. Changing the highlight options and adding a little custom css to the popup improves how everything looks.

leaflet(postcodes, width = "100%") %>% 
  setView(lng = -3.64, lat = 58, zoom = 7) %>%
  addTiles() %>% 
  addPolygons(fillOpacity = 0.2, popup = ~(pc_district), weight = 2,
              highlightOptions = highlightOptions(color = "#03F", weight = 5, 
                                                  bringToFront = TRUE))