计算 postcodes/zipcodes python 之间的(公路旅行)距离
Calculate (road travel) distance between postcodes/zipcodes python
我有一个包含开始和结束邮政编码(英国相当于美国邮政编码)的 csv 文件,我想计算两者之间的简单距离、道路行驶距离和行驶时间。我想要走的路是以一种或另一种方式使用 Google 地图。我首先尝试使用一些电子表格和以下 url http://maps.google.com/maps?saddr="&B2&"&daddr="&A2&" 但
- 我不知道如何从 google 地图中检索结果距离
- 我想知道一些更多的 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 中实现的示例:
计算两个英国邮政编码之间距离的最简单方法是不使用纬度和经度,而是使用东距和北距。
有了东距和北距后,您就可以使用毕达哥拉斯定理来计算距离,从而使数学计算变得更加简单。
获取邮政编码的东距和北距。您可以为此使用 Open Postcode Geo。
使用下面的公式计算距离:
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.
我有一个包含开始和结束邮政编码(英国相当于美国邮政编码)的 csv 文件,我想计算两者之间的简单距离、道路行驶距离和行驶时间。我想要走的路是以一种或另一种方式使用 Google 地图。我首先尝试使用一些电子表格和以下 url http://maps.google.com/maps?saddr="&B2&"&daddr="&A2&" 但
- 我不知道如何从 google 地图中检索结果距离
- 我想知道一些更多的 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 中实现的示例:
计算两个英国邮政编码之间距离的最简单方法是不使用纬度和经度,而是使用东距和北距。
有了东距和北距后,您就可以使用毕达哥拉斯定理来计算距离,从而使数学计算变得更加简单。
获取邮政编码的东距和北距。您可以为此使用 Open Postcode Geo。
使用下面的公式计算距离:
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.