GB postcode polygons – open data

[This article was first published on R – scottishsnow, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.


Postcode district and area polygons available.

These days I’m working with a lot of data about people. Often surveys, but also administrative data. I usually want to represent these on a map. To preserve anonymity I aggregate dataset before plotting them. This might be at a local authority level, but more often it is via postcode.

In the UK a postcode is used to define a small group of addresses and is of the form EH1 2NG (Edinburgh Castle), where the first half is the postcode district and the first letters (either 1 or 2) from the postcode district is the postcode area.

The Ordnance Survey release postcode point data as part of their Open Data offering, but to access postcode polygons one either needs to be an academic with an Edina account or pay a license fee for the Ordnance Survey product. I don’t often need access to individual postcode polygons, often aggregate ones are best. I sometimes download these from web sources, if I can find them, but the creation method isn’t that transparent – nor their licensing.

This post is announcing a new, derived dataset I’ve produced: postcode area and district polygons for GB. These have been created by making voronoi polygons of all GB postcodes and then dissolving boundaries based on postcode area and district. I’ve published this dataset on Figshare:

Download postcode polygons

The Figshare site also includes code to produce the polygons, but I’ll repeat it here too. The first code chunk uses R to prepare the postcode point data. The second code chunk uses GRASS to create the spatial dataset.


df = read_csv("~/GIS/OS/postcode.csv")

df = df %>%
   mutate(pc_district = str_sub(Postcode, 1, nchar(Postcode)-3)) %>%
   mutate(pc_district = trimws(pc_district)) %>%
   mutate(pc_area = gsub('[0-9]+', '', pc_district)) %>%
   mutate(pc_area = str_sub(pc_area, 1, 2))

write_csv(df, "~/GIS/OS/postcode_extra.csv")

And the GRASS commands used:

# GRASS commands for making postcode areas

v.voronoi input=postcodes@postcode output=pc_voronoi@postcode

v.dissolve input=pc_voronoi@postcode column=str_9 output=pc_area
v.dissolve input=pc_voronoi@postcode column=str_8 output=pc_district

v.overlay ainput=pc_area@postcode binput=GB_coast@postcode operator=and output=pc_area_clip
v.overlay ainput=pc_district@postcode binput=GB_coast@postcode operator=and output=pc_district_clip

v.db.renamecolumn map=pc_district_clip@postcode column=a_str_8,pc_district
v.db.renamecolumn map=pc_area_clip@postcode column=a_str_9,pc_area

db.dropcolumn -f table=pc_area_clip column=a_cat
db.dropcolumn -f table=pc_area_clip column=b_cat
db.dropcolumn -f table=pc_area_clip column=b_ID
db.dropcolumn -f table=pc_area_clip column=b_AREA
db.dropcolumn -f table=pc_area_clip column=b_PERIMETER
db.dropcolumn -f table=pc_area_clip column=b_ACRES
db.dropcolumn -f table=pc_district_clip column=a_cat
db.dropcolumn -f table=pc_district_clip column=b_cat
db.dropcolumn -f table=pc_district_clip column=b_ID
db.dropcolumn -f table=pc_district_clip column=b_AREA
db.dropcolumn -f table=pc_district_clip column=b_PERIMETER
db.dropcolumn -f table=pc_district_clip column=b_ACRES<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>

To leave a comment for the author, please follow the link and comment on their blog: R – scottishsnow. offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)