By Data Tricks, 12 September 2017
Update 02/02/2019: An updated version of this code has been posted here, which is reproducible as of Feb 2019.
There are many ways of plotting maps in R. In this tutorial we’re going to use the ggplot2 package to create a heatmap of England and Wales.
First let’s clear our memory, set the working directory and load some important packages.
rm(list=ls()) setwd("H:/R projects/R gallery") library(maps) library(mapdata) library(maptools) library(rgdal) library(ggmap) library(ggplot2) library(rgeos) library(broom) library(plyr)
A shapefile is a popular file format for geospatial data. Shapefiles are widely available; in the UK one of the most popular resources is the Office for National Statistics. You can find many useful datasets at geoportal.statistics.gov.uk but for the purposes of this exercise we are going to use the LAU Level 1 Full Clipped Boundaries file from here (valid as of 04/08/2017). To download the file, follow the link and click on Download > Shapefile and extract the zip file to your working directory.
In the UK, shapefiles are generally available at five levels of differing resolution as follows:
NUTS Level 1 Regions
NUTS Level 2 Counties
NUTS Level 3 Districts
LAU Level 1 Local authority districts
LAU Level 2 Local authority wards
It is important to note that at the more detailed levels (ie. LAU Levels 1 and 2), the more likely it is for borders to change. For instance, LAU areas correspond to electoral wards, the border of which have shifted in recent years. Depending on the task you are trying to accomplish, it is therefore sometimes better to analyse the higher levels which are less prone to change over time.
Now we can load the shapefile into R and structure it in a way that can be easily interpreted by ggplot2.
#Load the shapefile shapefile <- readOGR(dsn="/Map shapefiles", layer="Local_Administrative_Units_Level_1_December_2015_Full_Clipped_Boundaries_in_England_and_Wales") #Reshape for ggplot2 using the Broom package mapdata <- tidy(shapefile, region="lau115nm")
The mapdata object now contains coordinates of all the LAU boundaries. Type head(mapdata) to see what this looks like.
> head(mapdata) long lat order hole piece group id 1 515048.8 109605.9 1 FALSE 1 Adur.1 Adur 2 515060.2 109590.8 2 FALSE 1 Adur.1 Adur 3 515128.4 109603.4 3 FALSE 1 Adur.1 Adur 4 515161.3 109610.1 4 FALSE 1 Adur.1 Adur 5 515191.5 109586.9 5 FALSE 1 Adur.1 Adur 6 515245.9 109555.4 6 FALSE 1 Adur.1 Adur
We can straight away plot these boundaries on a ggplot map using the following code:
gg <- ggplot() + geom_polygon(data = mapdata, aes(x = long, y = lat, group = group), color = "#FFFFFF", size = 0.25) gg <- gg + coord_fixed(1) #This gives the map a nice 1:1 aspect ratio to prevent the map from appearing squashed print(gg)
Now that our data contains the coordinates of the local authority borders, we can then bring in data from other datasets to turn our basic map into a heat map. For the purposes of this tutorial, we are going to use a Land Registry dataset containing the number of applications for registrations, leases etc. made to the Land Registry in a given month. At the time of writing this was available here. Download the CSV file and save it to your working directory, then run the following code.
data <- read.csv("Number-of-applications-in-England-and-Wales-divided-by-local-authority-2017-06.csv") colnames(data) <- "id" #rename the first column to mirror column names in mapdata mapdata$id <- toupper(mapdata$id) #transform values in the id column to uppercase mapdata <- join(mapdata, data, by="id") #merge the two datasets mapdata$Total <- scale(mapdata$Total) #standardise the values in the Total column to ensure we get an even spread of colours across the map rather than very light or dark colours for outliers
Running the same code as in Step 4 but adding fill = Total to aes() will create a heat map.
gg <- ggplot() + geom_polygon(data = mapdata, aes(x = long, y = lat, group = group, fill = Total), color = "#FFFFFF", size = 0.25) gg <- gg + coord_fixed(1) print(gg)
We’re almost done! A map doesn’t look very good inside a chart grid so let’s remove the background, gridlines and axes to make it more appealing.
gg <- ggplot() + geom_polygon(data = mapdata, aes(x = long, y = lat, group = group, fill = Total), color = "#FFFFFF", size = 0.25) gg <- gg + scale_fill_gradient2(low = "blue", mid = "red", high = "yellow", na.value = "white") gg <- gg + coord_fixed(1) gg <- gg + theme_minimal() gg <- gg + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position = 'none') gg <- gg + theme(axis.title.x=element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank()) gg <- gg + theme(axis.title.y=element_blank(), axis.text.y = element_blank(), axis.ticks.y = element_blank()) print(gg)
And we’re done! You can always play around with the colours by using scale_fill_gradient for example by adding:
gg <- gg + scale_fill_gradient(low = "white", high = "red", na.value = "white")
Please note that your first comment on this site will be moderated, after which you will be able to comment freely.
You might also like
Creating Maps in R (2019)
Creating a heatmap of the UK in R
Leaflet maps in R
Create interactive location maps in R and embed onto websites or other applications.
UK population density map in R
Create a unique population density map of the UK in R using ggplot2 and geom_point.
Data Art: London mapped in R
Plotting an artistic map of London in R.
3D world map with plotly
Quickly plot data on a 3D world map with the plotly package for R.
Access more for free
Access more articles and code for free