Skip to content Skip to sidebar Skip to footer

Calculate (road Travel) Distance Between Postcodes/zipcodes Python

I have a csv file with start and end postcodes (UK equivalent of US zipcodes) and would like to compute simple distance, road travel distance and travel time between the two. I gue

Solution 1:

The distance between postal codes can be obtained with the pgeocode library. Unlike the above response, it does not query a web API, and is therefore more suitable for processing large amounts of data,

 >>> import pgeocode

 >>> dist = pgeocode.GeoDistance('GB')
 >>> dist.query_postal_code('WC2N', 'EH53')
 536.5# retured distance in km

More information about these postal codes, including latitude and longitude, can be queried with,

 >>> nomi = pgeocode.Nominatim('GB') >>> nomi.query_postal_code(['WC2N', 'EH53'])
   postal_code country code                                     place_name  \
 0        WC2N           GB                                         London   
 1        EH53           GB  Pumpherston, Mid Calder, East Calder, Oakbank   

   state_name state_code     county_name county_code community_name  \
 0    England        ENG  Greater London    11609024            NaN   
 1   Scotland        SCT    West Lothian         WLN            NaN   

   community_code  latitude  longitude  accuracy  
 0            NaN   51.5085  -0.125700       4.0  
 1            NaN   55.9082  -3.479025       4.0

This uses the GeoNames postal code dataset to get the GPS coordinates, then computes the Haversine (great circle) distance on those. Most countries are supported.

In the particular case of Great Britain, only the outward codes are included in the GB dataset, the full dataset is also available as GB_full but it is currently not supported in pgeocode.

Solution 2:

The main issue with finding a distance between 2 postcodes is that they aren't designed for it.

For the purposes of directing mail, the United Kingdom is divided by Royal Mail into postcode areas. -Wikipedia

A postcode by itself provides no useful information, so you are correct you need help from an external source. The Google maps service at http://maps.google.com is of no use, as it's not designed for you to retrieve information like this.


Option 1 - Google Maps API

The Google Maps API is feature packed and will provide you with a lot of options. The link above is to the Distance Matrix API, which will help with working out distances between 2 points. The results from this will be based on travel (so driving distance), this may or may not be what you want.

Example

Python 3

import urllib.request
import json

res = urllib.request.urlopen("https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=SE1%208XX&destinations=B2%205NY").read()
data = json.loads(res.decode())
print(data["rows"][0]["elements"][0]["distance"])
# {'text': '127 mi', 'value': 204914}

Note: Google Maps API is subject to usage limits.

Option 2 - Do it yourself with postcodes.io

postcodes.io has a nice API backed by a public data set. Example lookup. Results are in JSON which can be mapped to a Python dictionary using the json module. The downside here is it provides no way to check distance, so you will have to do it yourself using the Longitude and Latitude returned.

Example

Python 3

import urllib.request
import json

res = urllib.request.urlopen("http://api.postcodes.io/postcodes/SE18XX").read()
data = json.loads(res)
print(data["result"]["longitude"], data["result"]["latitude"])
# -0.11682549420451251.5057668390097

Calculating distance

I don't want to get too much into this because it's a big topic and varies greatly depending on what you're trying to achieve, but a good starting point would be the Haversine Formula, which takes into account the curvature of the Earth. However, it assumes the Earth is a perfect sphere (which it's not).

The haversine formula determines the great-circle distance between two points on a sphere given their longitudes and latitudes. Important in navigation, it is a special case of a more general formula in spherical trigonometry, the law of haversines, that relates the sides and angles of spherical triangles.

Here is an example of it implemented in Python: https://stackoverflow.com/a/4913653/7220776

Solution 3:

This looks like the perfect resource for you (they provide lat and long values for each postcode in the UK, in various formats): https://www.freemaptools.com/download-uk-postcode-lat-lng.htm and in particular this CSV file (linked in the same page): https://www.freemaptools.com/download/full-postcodes/ukpostcodes.zip

Once you match geographical coordinates to each postcode you have (out of the scope of this question), say you'll have a table with 4 columns (i.e. 2 (lat, long) values per postcode). You can compute the distances using numpy. Here's an example:

import numpy as np
latlong = np.random.random((3,4))
# Dummy table containing 3 records, will look like this:# array([[ 0.258906  ,  0.66073909,  0.25845113,  0.87433443],#        [ 0.7657047 ,  0.48898144,  0.39812762,  0.66054291],#        [ 0.2839561 ,  0.04679014,  0.40685189,  0.09550362]])# The following will produce a numpy array with as many elements as your records# (It's the Euclidean distance between the points)
distances = np.sqrt((latlong[:, 3] - latlong[:, 1])**2 + (latlong[:, 2] - latlong[:, 0])**2)
# and it look like this:# array([ 0.21359582,  0.405643  ,  0.13219825])

Solution 4:

The simplest way to calculate the distance between two UK postcodes is not to use latitude and longitude but to use easting and northing instead.

Once you have easting and northing you can just use Pythagoras's theorem to calculate the distance, making the maths much simpler.

  1. Get the easting and northing for the postcodes. You can use Open Postcode Geo for this.

  2. Use the below formula to find the distance:

sqrt(pow(abs(easting1 - easting2),2) + pow(abs(northing1 - northing1),2))

This example is from MySQL but you should be able to find similar functions in both Excel and Python:

  • sqrt(): Find the square root.
  • pow(): Raise to the power of.
  • abs(): Absolute value (ignore sign).

Post a Comment for "Calculate (road Travel) Distance Between Postcodes/zipcodes Python"