Identifying UK Country from Eastings and Northings

Recently when working with the UK Biobank (UKB) dataset, I had to determine from a location’s Eastings and Northings whether it is located in England, Scotland, or Wales. I have very little background in working with geospatial data, and I figured that some other people working with the dataset might not have either, so here I have documented how I approached the problem in Python. My approach involved transforming the Eastings and Northings to longitudes and latitudes, and intersecting them with the boundaries of England, Scotland, and Wales.

The first thing to note is that there are many different co-ordinate reference systems (CRS). The UKB co-ordinates are given in Eastings and Northings, which are a type of CRS that uses a 2D map as its basis. In contrast, the more commonly encountered longitudes and latitudes define a point on the 3D globe. The map used to define UKB Eastings and Northings is Ordnance Survey Great Britain 1936 (OSGB36).

The code block below creates a DataFrame containing OSGB36 Eastings and Northings for locations within the capitals of England, Scotland, and Wales in a similar format to that provided by UKB.

import pandas as pd 

locs = pd.DataFrame({
   "northing": [180381, 673842, 176329], 
   "easting": [530034, 325265, 318371],
   "city": ["london", "edinburgh", "cardiff"]
})

I used a Python library called geopandas, which has lots of useful things for working with geospatial data.

import geopandas as gpd

Geopandas has a class called a Point, which is exactly what it sounds like: a point defined by a pair of xy co-ordinates. We can transform our co-ordinates into this class using the points_from_xy() function. We must tell geopandas what CRS the co-ordinates belong to. Each different CRS has a unique identifier, and you can find out which is relevant to you by looking it up at https://epsg.io/. Searching for “ordnance survey great britain”, we see that the relevant identifier is EPSG:27700.

coords = gpd.points_from_xy(
	locs["easting"], locs["northing"], 
	crs="EPSG:27700"
)

We can check that this is right CRS identifier by checking the crs attribute of the Point array we have created using:

coords.crs

Which gives the output:

<Projected CRS: EPSG:27700>
Name: OSGB36 / British National Grid
Axis Info [cartesian]:
- E[east]: Easting (metre)
- N[north]: Northing (metre)
Area of Use:
- name: United Kingdom (UK) - offshore to boundary of UKCS within 49°45'N to 61°N and 9°W to 2°E; onshore Great Britain (England, Wales and Scotland). Isle of Man onshore.
- bounds: (-9.0, 49.75, 2.01, 61.01)
Coordinate Operation:
- name: British National Grid
- method: Transverse Mercator
Datum: Ordnance Survey of Great Britain 1936
- Ellipsoid: Airy 1830
- Prime Meridian: Greenwich

The locations I was working with were rounded to the nearest kilometre. This rounding could place a co-ordinate off-shore, which would cause problems when I tried to determine whether they were within the borders of a country. To account for this rounding, I transformed my point co-ordinates into circles with a 500 metre diameter using the buffer() method. The units of the value passed to this method depend on the CRS. As we can see from the output of coords.crs, this unit is metres for OSGB36.

polys = coords.buffer(500)

In geopandas, the Polygon class is used to represent areas like the circles created here. My goal was to identify whether these areas are located in England, Scotland, or Wales. The boundaries of these countries can be obtained from the Office of National Statistics’ Open Geography Portal. Navigate to Boundaries > OECD/Eurostat Boundaries > NUTS1 > 2018 Boundaries. NUTS stands for Nomenclature of Territorial Units for Statistics, which describes territory boundaries at various levels. NUTS1 is the highest level, in which Scotland, Northern Ireland, and Wales are represented by a single region, and there are a number of regions that make up England. From this site you can download these boundaries in geojson format and read them into Python as GeoDataFrames using geopandas.

uk = gpd.read_file("nuts1_boundaries.geojson")

Below is the output of uk.head(n=2):

objectid	nuts118cd	nuts118nm	bng_e	bng_n	long	lat	st_areashape	st_lengthshape	geometry
1	UKC	North East (England)	417313	600358	-1.72890	55.297031	8.675727e+09	7.954563e+05	MULTIPOLYGON (((-2.03012 55.80992, -2.03019 55...
2	UKD	North West (England)	350015	506280	-2.77237	54.449451	1.491948e+10	1.089508e+06	POLYGON ((-2.67559 55.17332, -2.67504 55.17351...

You can produce the following plot with uk.plot():

Output of gb.plot(): graph of the UK

The UK boundaries are given in longitudes and latitudes (specifically the WGS84 system, which is the co-ordinate system used by GPS). You can see this by executing uk.crs, which gives the following output:

<Geographic 2D CRS: EPSG:4326>
Name: WGS 84
Axis Info [ellipsoidal]:
- Lat[north]: Geodetic latitude (degree)
- Lon[east]: Geodetic longitude (degree)
Area of Use:
- name: World.
- bounds: (-180.0, -90.0, 180.0, 90.0)
Datum: World Geodetic System 1984 ensemble
- Ellipsoid: WGS 84
- Prime Meridian: Greenwich

To intersect these regions with the capital city locations, they must be using the same co-ordinate system. I transformed the capital city locations from OSGB36 to WGS84.

locs["geometry"] = polys.to_crs("EPSG:4326")
locs = gpd.GeoDataFrame(locs)

Geopandas provides sjoin() for performing intersections between two GeoDataFrames. In the example below, for each set of city co-ordinates, this function determines which of the NUTS1 UK regions they are located in.

intersection = gpd.sjoin(
   locs,
   uk,
   how = "left",
   predicate = "intersects"
)

intersection[["nuts118nm", "city"]].head() should give you:

	nuts118nm	city
London	london
Scotland	edinburgh
Wales	cardiff

From the output above, you can see that the London location is located in the NUTS1 region London, Edinburgh in Scotland, and Cardiff in Wales, as we’d expect. And just like that, you can figure out the UK country that any set of co-ordinate locations are in.

References

Ordnance Survey (2015) A guide to co-ordinate systems in Great Britain. https://www.bnhs.co.uk/2019/technology/grabagridref/OSGB.pdf, accessed 19/03/2022.