Postcode Polygons on a Leaflet Map

May 30, 2018    leaflet

I have been using Leaflet for a little while now but always as part of a shiny app. However, as Mike Spencer went to all the trouble of producing polygons for GB postcode areas and districts I thought this was a good opportunity for a blog post (Spencer 2018).

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 = readOGR("postcode_polygons.gpkg", layer = "postcode_district")

For leaflet to be able to plot these they need to be in terms of latitude and longitude rather than Easting and Northing. We can check the current projection:

[1] "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +units=m +no_defs"

and convert them to latitude and longitude.

postcodes = spTransform(postcodes, CRS("+proj=longlat +datum=WGS84"))
[1] "+proj=longlat +datum=WGS84 +no_defs"

For a lot more detail on different coordinate systems this pdf seems like a reasonable place to start.

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.

postcodes = subset(postcodes, grepl("IV", postcodes$pc_district))

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))