Rough guide to building UK election maps for D3.js (Revisited Dec 2019)
Updated again for December 2019 - see bottom for updated links
This post was originally published on my blog in March 2016.
Between the summer of 2014 and summer of 2015, I worked as a front end developer at CITY A.M., a free daily newspaper distributed across London and beyond. Towards the end of my time there, I helped to build an interactive British General Election Map. This post outlines how I created it.
Disclaimer
Here we are in June 2017. As I write, the UK have just held their snap election. CITY A.M. have repurposed the same map for the 2017 election, with the added bonus that it has been tinkered to fit with their new site design, which the original didn't cope with too well. Otherwise, it's the same code.
Strong and stable, eh?
There's a couple of things I need to mention beforehand:
A fair amount of time has passed since this project was completed, so forgive me if I appear to have skipped over the details. Although the map has been repurposed for the 2017 election, my Codepen is based on the 2015 results.
Let's see the map then
Here's a simplified version of the map. Use your mouse to hover or tap on the constituency boundaries to view the results:
Here, the map looks rather small, as it has been resized to fit the page. You can use your mouse wheel (or double-click/double-tap) to zoom in or out of the map, and click constituencies to view more detailed results on the left hand side. Each constituency is coloured according to that party's brand livery.
This is only a very general guide as to how that map was created. I did promise to add further detail after this initial post, but have never got around to it. My memory of how I put it together is now full of holes.
Acknowledgements
This project was the work of several people, in addition to myself. Here are the other former colleagues who collectively made the election map possible:
- Michael King (back end programming of data capture system)
- Billy Ehrenberg (for D3.js support and data journalism expertise)
- Emma Haslett (who toiled through the night gathering the results)
- Chris Parameter (design and feel of interactive visuals)
- Ben Barden (project management)
Thank you all!
Introduction
Many news organisations - such as BBC News or The Guardian - put a lot of resources into their election coverage (in fact, the election map BBC News have created looks kind of similar to mine/CITY A.M's). Way back in 2010, Adobe Flash was primarily used to produce interactive mapping solutions. Now we have at our disposal a wider range of tools with which to produce compelling content, without resorting to plug-ins.
To produce our map, we needed the following:
- a suitable back end with which to collate the results data
- a map of all of the 650 parliamentary constituencies which comprise England, Wales, Scotland and Northern Ireland.
- a way to bind the data to the map
- making the election map usable on mobile and tablet devices.
That's no mean feat - there are a lot of moving parts!
In the end, the following resources and technologies were used, in no order of importance:
- D3.js
- Mapshaper.org
- Ordnance Survey
- Ordnance Survey of Northern Ireland
- QGIS
- Laravel PHP framework
- a lot of testing on iPads and iPhones
D3.js - or Data Driven Documents - is a Javascript library that binds data to elements of the Document Object Model (DOM) that are present - or yet to be created - on your web page. It's a piece of magic. You give it data, and inform it as to how you want the data to be displayed visually. D3.js then does the rest.
First released back in 2011 by Mike Bostock, it has grown exponentially in its popularity. The website alone is worth a visit, to see the myriad visualisations that are possible. It practically gave rise to data journalism, and lead to renewed interest in data science. The gradual open sourcing of governmental data and statistics has made the visualisation of previously impenetrable data far more achievable, helping to reveal trends that would never have been seen previously.
D3.js follows web standards, and no proprietary solutions, so is extremely adaptable. It offers a deceptively simple syntax (similar to jQuery), but is more than capable of producing extremely compelling and beautiful data visualisations.
Building a map
For mapping, D3 supports various projections, in data formats such as GeoJSON or TopoJSON. If you care about file size or topology, then use TopoJSON. Otherwise, use GeoJSON.
Playing with map data is actually rather involved. Fortunately, Mike Bostock's D3.js article "Let's make a Map" is well worth a read (this has been superceded by a more recent page, Command Line Cartography, which uses US data as a case study). It happens to use the UK and Ireland as an example map, so some of the technical detail described within is very useful! My only problem was that I was using Windows to develop the map. Therefore, references to Homebrew had to be replaced with Windows equivalents, which proved to be a bit of a minefield.
However, most available mapping data comes in ESRI Shapefile format, for use in geographical mapping software, such as QGIS. So, we need to get hold of this data. As Bostock's article attests, Natural Earth provide some great geographical data provided entirely by voluntary contributors.
The primary source of mapping data for parliamentary constituencies is the Ordnance Survey. Under their OS OpenData resource, you can download their datasets for free, under an open source licence. For authoritative data such as elections, it's important to get data from an official source. As of 2019, the OS Boundary Line page contains access to the dataset for Westminster constituencies.
However, the first thing to realise is that Northern Ireland mapping data is owned by a separate service - the Ordnance Survey of Northern Ireland. We therefore need to obtain maps from both services, then combine them.
This is where the QGIS software comes into its own. QGIS is a hefty piece of software, and is well beyond the scope of this article, but is available for all major platforms as a free download. With QGIS, we can import both Shape files. We then export a new Shape file of the combined data. Once that is done, we can finally import the file into the Mapshaper.org site, and export a more simplified GeoJSON file, ready for our purposes.
The building of the map is the part of the journey I've had to skip through for the time being. Rather than get into the nitty gritty of this, please read my December 2019 update, as I link to an article that covers this in great detail.
Data binding
In order to marry the constituencies to the election result data, a unique identifier was required. In this case, the common element was that used by the Press Association. This id is a simple integer value, which enabled D3.js to bind the data more quickly.
The main nub of the code is this:
queue()
.defer(d3.json, "map file")
.defer(d3.json, "election data")
.await(ready);
...
function ready(error, uk, boundaries) {
mapFeatures = topojson.feature(uk, uk.objects.subunits).features;
var map = mapContainer
.append("g")
.attr("class","subunits")
.selectAll("path")
.data(mapFeatures),
constituency = boundaries.data,...
The queue
command allows for the loading of large datasets asynchronously. The await
handler has a single argument, the function that builds the map, called ready()
. The ready()
function then maps the election result data to the constituency subunit features.
The function call has three arguments, error, uk
and boundaries
. The last two correlate to the data sources referred to in the defer()
handlers of the queue()
command. In this instance, uk
maps to the map file, while boundaries
maps to the election data. The map
variable is an instance of the SVG file which will contain all of the map data and election data combined.
Mobile and Tablet
As the election map had to be usable on mobile devices, the map file used on the webpage had to be simplified further. Overly complex SVG files render very poorly on tablets and mobile devices (although devices are improving in processing speed, there will always be many older devices that will struggle, so optimisation is mandatory), so the mapfile had to be reduced in size and complexity, a function the Mapshaper.org site offers. CSS breakpoints were then used to serve mobile and tablet specific versions which would work accordingly. D3.js supports touch and swipe events as standard.
Again, this will need to be the subject of another post, as it requires deeper explanation than can be provided for the time being.
Conclusion
This election map solution is adequate, but is merely one approach. There are sure to be other ways of producing a data visualization such as this. Much of the code was put together fairly quickly, with various iterations performed in initial research and discovery phase. Added complexity came in the form of mobile and tablet support. Much throttling had to be performed to prevent slow performance. SVG files don't work too well if they are too complex in structure and require features such as pan and zoom.
The D3.js library, and it's accompanying Queue library are available as Node NPM modules, which can be beneficial in preparing server side mapping solutions. The Javascript itself is very messy in this implementation, and can be clearly improved.
Although much of what I've written here will age over time, I do hope to be able to write further, more comprehensive accounts on some of the above in due course. Thanks for reading.
2019 Addendum
Data science and browser technology have continued to march forward. In the years since I last took a look at mapping, a lot has clearly happened. D3.js has improved immeasurably, SVG support has been bolstered in browsers, while CSS and Javascript have been improved with new techniques and layout methods. All of this serves to make the manipulation of data and vector graphics easier than ever.
Data and statistics collation has become more granular and expansive. Together with the open sourcing of more and more datasets from government, it is a lot easier to gain access to, and process such data. The potential complexity of such work is mind boggling.
With that, I leave you with a set of links, which will prove most useful, in preparing for the next election, wherever you are in the world (even if some of what I list below is Uk centric, the techniques will apply to all parts of the world)
- Ordnance Survey Github - I had no idea OS had a Github account. This is full of a wealth of material.
- Ordnance Survey Election Maps - OS have themselves created a set of election maps for the UK and Northern Ireland.
- Ordnance Survey OS Boundary-Line - free to download and use, all the data you need, from Euro constituencies to parish ward boundaries, for electoral data mapping.
- OSNI Data Portal - Ordnance Survey of Northern Ireland's Open Data portal. As of 2019, the site is a little broken. This is likely due to lack of maintenance, as the Stormont assembly has not functioned since early 2017.
- Command Line Cartography - mentioned earlier in the post, this is an update of Mike Bostock's Let's Make a Map D3 article. It is very extensive, and comes in the form of four articles (read part 2, part 3 and part 4)
December 2019 Addendum
As I write, the 2019 General Election exit poll has been published, and the news organisations are now beginning their long night of publishing constituency results, and updating their revised mapping pages.
I've now published a new post about the 2019 Election, which neatly dovetails with this one. The links to the news websites can now be found in that post.