计算 postcodes/zipcodes python 之间的(公路旅行)距离

Calculate (road travel) distance between postcodes/zipcodes python

我有一个包含开始和结束邮政编码(英国相当于美国邮政编码)的 csv 文件,我想计算两者之间的简单距离、道路行驶距离和行驶时间。我想要走的路是以一种或另一种方式使用 Google 地图。我首先尝试使用一些电子表格和以下 url http://maps.google.com/maps?saddr="&B2&"&daddr="&A2&" 但

  1. 我不知道如何从 google 地图中检索结果距离
  2. 我想知道一些更多的 pythonic 方法来解决这个问题

这看起来是适合您的完美资源(它们以各种格式为英国的每个邮政编码提供经纬度值):https://www.freemaptools.com/download-uk-postcode-lat-lng.htm 特别是这个 CSV 文件(链接在同一页): https://www.freemaptools.com/download/full-postcodes/ukpostcodes.zip

一旦你将地理坐标与你拥有的每个邮政编码相匹配(超出了这个问题的范围),假设你将有一个包含 4 列的 table(即每个邮政编码 2 个(lat,long)值). 您可以使用 numpy 计算距离。这是一个例子:

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])

查找 2 个邮政编码之间的距离的主要问题是它们不是为此设计的。

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

邮政编码本身并不能提供有用的信息,因此您是对的,您需要外部资源的帮助。 http://maps.google.com 的 Google 地图服务没有用,因为它不是为您检索此类信息而设计的。


选项 1 - Google Maps API

Google 地图 API 功能丰富,将为您提供多种选择。上面的 link 是距离矩阵 API,这将有助于计算两点之间的距离。结果将基于旅行(即行驶距离),这可能是也可能不是您想要的。

例子

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.

选项 2 - 使用 postcodes.io

自己动手

postcodes.io 有一个很好的 API 由 public 数据集支持。 Example lookup. Results are in JSON which can be mapped to a Python dictionary using the json 模块。这里的缺点是它无法提供检查距离的方法,因此您必须使用返回的经度和纬度自行完成。

例子

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.116825494204512 51.5057668390097

正在计算距离

我不想过多地讨论这个问题,因为它是一个很大的话题,并且根据您要实现的目标而有很大差异,但是 Haversine Formula 是一个很好的起点,它需要考虑到地球的曲率。但是,它假设地球是一个完美的球体(事实并非如此)。

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.

这是在 Python 中实现的示例:

计算两个英国邮政编码之间距离的最简单方法是不使用纬度和经度,而是使用东距和北距。

有了东距和北距后,您就可以使用毕达哥拉斯定理来计算距离,从而使数学计算变得更加简单。

  1. 获取邮政编码的东距和北距。您可以为此使用 Open Postcode Geo

  2. 使用下面的公式计算距离:

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

此示例来自 MySQL,但您应该能够在 Excel 和 Python 中找到类似的函数:

  • sqrt():求平方根。
  • pow(): 提升到的幂。
  • abs():绝对 值(忽略符号)。

邮政编码之间的距离可以通过pgeocode库获得。与上面的响应不同,它不查询网页API,因此更适合处理大量数据,

 >>> import pgeocode

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

有关这些邮政编码的更多信息,包括纬度和经度,可以查询,

 >>> 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

这使用 GeoNames postal code dataset 获取 GPS 坐标,然后计算其上的 Haversine(大圆)距离。支持大多数国家/地区。

在英国的特殊情况下,GB 数据集中仅包含外向代码,完整数据集也可作为 GB_full 使用,但目前 not supported pgeocode.