Dissolving polygons is another fairly elementary GIS task that I need to perform regularly. With R this is can be a bit involved, but once done is fully reproducible and the code can be re-used. This post is essentially a companion piece to Clipping polygons in R; I wrote both because I often forget how to complete these tasks in R.
Let’s gather together everything we need to complete this example. We need a shapefile of small geographies to ‘dissolve’, a lookup table to tell us which polygons dissolve into which, and we need a couple of R spatial packages to run everything. Let’s get started.
# The default behaviour of this script is to create a folder called 'dissolve-example' # and download and run everything from here. # You can change this by modifying the next two lines dir.create("dissolve-example") setwd("dissolve-example") # Load a few packages. dplyr makes merges easier require("rgdal") require("rgeos") require("dplyr") # Set up shapefile to dissolve. I'm using English regions download.file("http://census.edina.ac.uk/ukborders/easy_download/prebuilt/shape/England_gor_2011.zip", destfile = "lad-region-lookup.zip") unzip("lad-region-lookup.zip", exdir = ".") region <- readOGR(".", "England_gor_2011") # Check the shapefile has loaded correctly plot(region)
# We're going to dissolve all regions in to one country (England!) # For this we'll create a lookup table and merge with the spatial data # Hopefully for your 'real' data you have a lookup table of all polygons and # their larger geography already! lu <- data.frame() lu <- rbind(lu, region@data) lu$CODE <- as.character(lu$CODE) lu$NAME <- as.character(lu$NAME) lu$country <- NA lu$country <- "England"
We now need to merge the lookup table into our spatial object data frame. We should end up with one row per zone to dissolve, each with a reference for the relevant larger geography. I think the trick is to make sure the row names match exactly, and if you can match the polygon IDs as well with spChFIDs().
# Merge lu (LookUp) into polygons, region@data$CODE <- as.character(region@data$CODE) region@data <- full_join(region@data, lu, by = "CODE") # Tidy merged data region@data <- select(region@data, -NAME.x) colnames(region@data) <- c("code", "name", "country") # Ensure shapefile row.names and polygon IDs are sensible row.names(region) <- row.names(region@data) region <- spChFIDs(region, row.names(region))
Now we can do the dissolve. I use gUnaryUnion (and indeed I think unionSpatialPolygons in the maptools package uses this by default).
# Now the dissolve region <- gUnaryUnion(region, id = region@data$country)
If you want to just plot this using base plot you can stop there. If you want to do anything with the data or plot using ggplot you need to recreate the data frame.
# If you want to recreate an object with a data frame # make sure row names match row.names(region) <- as.character(1:length(region)) # Extract the data you want (the larger geography) lu <- unique(lu$country) lu <- as.data.frame(lu) colnames(lu) <- "country" # your data will probably have more than 1 row! # And add the data back in region <- SpatialPolygonsDataFrame(region, lu) # Check it's all worked plot(region)
Your plot should look like this:
And your data frame should look like this:
region@data ## country ## 1 England