A common problem when trying to show data is that the attributes that you want to map for comparison are stored in multiple rather than single variables. For example, proportion of employment by type. This practical will achieve tis using reshape2, ggplot and maptools.
library(reshape2) library(ggplot2) library(maptools)
Download the the dataset from here and unzip to a suitable directory.
londonData <- read.csv("ward_atlas_2011_employment.csv") londonShape <- readShapePoly("london_sport.shp") [email protected]$id = rownames([email protected])
As you are probably now aware, the data for London is at ward level. For this visualisation, we want to reduce this to boroughs. The first step is to work out borough codes which are the first 4 characters of the ward code (Codes). i.e for the ward 00ABGB the borough code is ooAB. This is Achieved with the substr() function in base R.
londonData$ward <- substr(londonData$Codes,1,4)
With all records now holding a borough code we can use the melt() function in the reshape2 package. The melt function then creates a unique row for each id field and variable. We specify id variables in the underlined section.
LondonDataMelt <- melt(londonData, id.vars=c("Codes", "Names", "ward"))
|1||00AA||City of London||00AA||X1_2_Agriculture_mining_utilities||0.00|
With the majority of our data processing complete we now need to prepare the shapefiles for plotting. Format conversion is achieved using fortify() which is part of the ggplot2 package. the _geom extension indicates that it contains the shapefile geometry.
gpclibPermit() london_geom <- fortify(londonShape, region="id")
With the shapefile fortified, we can now do the appropriate joins to bring our data back together. First, we join the melted borough data to the original shapefile attribute data. The attribute data is obtain by appending @data to the object. The second join merges the London_geometry and shapefile data.
[email protected] <- merge([email protected], LondonDataMelt, by.x="ons_label", by.y="ward") london_geom <- merge(london_geom, [email protected], by.x="id", by.y="id")
A small addition before creating the plot is the creation of labels. This is achieved by taking the mean of lat and long for each polygon. Though not a perfect solution it is fairly efficient. An alternative may be coordinates() in the sp package
burNames <- aggregate(cbind(long, lat) ~ ons_label, data=london_geom, FUN=mean)
Finally we can construct our plot. If you want to suppress the labelling simply insert a # in front of the geom_text line.
ggplot(london_geom, aes(x=long, y=lat)) + geom_polygon(data=london_geom, aes(group=group, fill=value)) + geom_text(data=burNames, aes(long, lat, label = ons_label, col="white") ,size=3) + facet_wrap(~variable)+ scale_x_continuous("", breaks=NULL) + scale_y_continuous("", breaks=NULL)
The output should be something like this: