【问题标题】:Calculate (road travel) distance between postcodes/zipcodes python计算邮政编码/邮政编码python之间的(公路旅行)距离
【发布时间】:2017-10-25 20:39:11
【问题描述】:

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

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

【问题讨论】:

    标签: python google-maps zipcode postal-code


    【解决方案1】:

    邮政编码之间的距离可以通过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 postal code dataset 获取 GPS 坐标,然后计算这些坐标上的 Haversine(大圆)距离。支持大多数国家/地区。

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

    【讨论】:

      【解决方案2】:

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

      出于直邮的目的,英国被划分为 皇家邮政进入邮政编码区。 -Wikipedia

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


      选项 1 - Google Maps API

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

      示例

      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 受usage limits 约束。

      选项 2 - 使用 postcodes.io 自己动手

      postcodes.io 有一个由公共数据集支持的优秀 API。 Example lookup。结果采用 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,它考虑了曲率地球的。但是,它假定地球是一个完美的球体(事实并非如此)。

      haversine 公式确定两个之间的大圆距离 给定其经度和纬度的球体上的点。重要的 导航,它是一个更一般的公式的特例 球面三角学,haversines 定律,与边相关 和球面三角形的角度。

      这是一个用 Python 实现的示例:https://stackoverflow.com/a/4913653/7220776

      【讨论】:

      • 完全正确。地理距离与欧几里得距离相同。例如,纵向距离被计算为纬度的函数。当您考虑从东 1 度线到东 2 度线时,这是有道理的;在赤道,这远远超过 50 英里,但离北极或南极非常近,这将是一个很小的距离。 Haversine 公式说明了这一点。另请参阅Vincenty's Formulae 了解地球表面的方程式。
      • @alxwrd 谢谢!关于如何调用 Google API 和读取 JSON 的 python 代码正是我想要的。但是,您的代码对我不起作用(python 3.5): data = json.loads(res) 给了我 TypeError:JSON 对象必须是 str,而不是“字节”。我现在将您的答案修改为 data = json.loads(res.decode()) 并且它按预期工作。
      • 再次感谢您:我最终也使用了 postcodes.io。这个答案已经两次有用了!
      【解决方案3】:

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

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

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

      2. 使用以下公式求距离:

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

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

      • sqrt():求平方根。
      • pow():提高到权力。
      • abs(): 绝对 值(忽略符号)。

      【讨论】:

        【解决方案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])
        

        【讨论】:

        • 在这种情况下使用欧几里得距离是不正确的,应该使用Haversine(大圆)距离。
        • 同意。这是一种近似方法。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        • 1970-01-01
        • 1970-01-01
        • 2010-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多