计算邮政编码/邮政编码之间的(道路旅行)距离python

9
我有一个包含起始和终止邮编(英国版的美国zipcodes)的csv文件,希望计算两个地点之间的简单距离、道路行驶距离以及时间。我猜想使用Google地图是一种可行的方式。我最初尝试使用某些电子表格和以下网址:http://maps.google.com/maps?saddr="&B2&"&daddr="&A2&"但是,
  1. 我不知道如何从Google地图中检索出距离
  2. 我想了解更多Pythonic的方法来计算这个问题
4个回答

25

可以使用pgeocode库来获取邮政编码之间的距离。与上述响应不同,它不会查询Web 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邮编数据集获取GPS坐标,然后计算它们之间的哈弗辛距离(大圆距离)。支持大多数国家。

对于英国,仅包含外向代码在GB数据集中,完整数据集也可用作GB_full,但目前在pgeocode中不受支持


1
这只涵盖简单的距离吗?还是可以计算道路旅行距离和旅行时间? - FortuneFaded
1
仅适用于地理距离。 - rth

15

找到两个邮政编码之间的距离的主要问题在于它们并不是为此而设计的。

为了邮寄方便,英国被皇家邮政分成了邮政编码区域。-维基百科

单独一个邮政编码并没有提供有用的信息,因此您需要从外部来源获取帮助。Google Maps服务无法提供帮助,因为它并不是为您检索此类信息而设计的。


选项1 - Google Maps API

Google Maps API功能丰富,提供了许多选项。上面的链接是距离矩阵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}

注意:Google Maps API受使用限制

选项2 - 使用postcodes.io自行完成

postcodes.io拥有一个很好的API,由公共数据集支持。示例查找。结果以JSON格式呈现,可以使用json模块将其映射到Python字典中。这里的缺点是它没有提供检查距离的方法,因此您将不得不使用返回的经度和纬度自行完成。

示例

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,它考虑了地球的曲率。然而,它假设地球是一个完美的球体(而实际上并不是这样)。

哈弗辛公式确定了两个点在球面上的经度和纬度之间的大圆距离。在导航中很重要,它是球面三角学中更一般公式的一个特殊情况,即哈弗辛定理,它关联了球面三角形的边和角度。

这是一个在Python中实现它的例子:https://dev59.com/mW445IYBdhLWcg3wWI2L#4913653


1
完全正确。地理距离与欧几里得距离不同。例如,经度距离是纬度的函数。当你考虑从1度东经到2度东经旅行时,这是有意义的;在赤道上,这超过了50英里,但在南北极附近非常接近,这将是一个微小的距离。Haversine公式可以解决这个问题。还可以查看文森特公式,以获得在地球表面上的方程式。 - DatHydroGuy
@alxwrd 谢谢!你提供的如何调用Google API并读取JSON的Python代码正是我在寻找的。然而,你的代码在我的电脑上无法运行(Python 3.5):data = json.loads(res) 报错 TypeError: the JSON object must be str, not 'bytes'。我现在修改了你的答案,变成了 data = json.loads(res.decode()),现在它可以正常工作了。 - famargar
1
需要再次感谢您:我最终也使用了postcodes.io。这个答案已经两次帮到我了! - famargar

4
这似乎是一个完美的资源(他们为英国每个邮政编码提供了纬度和经度值,以各种格式呈现):https://www.freemaptools.com/download-uk-postcode-lat-lng.htm,特别是这个 CSV 文件(在同一页中链接):https://www.freemaptools.com/download/full-postcodes/ukpostcodes.zip 一旦您将地理坐标与每个邮政编码匹配(超出本问题的范围),您将拥有一个带有4列的表格(即每个邮政编码的2个(纬度、经度)值)。您可以使用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
在这种情况下使用欧几里得距离是不正确的,应该使用Haversine(大圆)距离。 - rth
同意。这是一种近似的方法。 - teoguso

1

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

一旦你得到了东北坐标,就可以使用勾股定理来计算距离,使数学计算更简单。

  1. 获取邮编的东北坐标。您可以使用Open Postcode Geo进行此操作。

  2. 使用以下公式查找距离:

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

这个例子来自MySQL,但是你应该能够在Excel和Python中找到类似的函数:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接