【问题标题】:Given a lat/long, find the nearest location based on a json list of lat/long给定一个 lat/long,根据 lat/long 的 json 列表找到最近的位置
【发布时间】:2018-03-20 09:11:48
【问题描述】:

给定一个json文件,

{"BusStopCode": "00481", "RoadName": "Woodlands Rd", "Description": "BT PANJANG TEMP BUS PK", "Latitude": 1.383764, "Longitude": 103.7583},
{"BusStopCode": "01012", "RoadName": "Victoria St", "Description": "Hotel Grand Pacific", "Latitude": 1.29684825487647, "Longitude": 103.85253591654006}

,等等……

在各种公交车站中,我试图根据 5000 个公交车站的列表找到最近的公交车站,任何用户都使用给定的公式给出纬度/经度

import math
R = 6371000 #radius of the Earth in m
x = (lon2 - lon1) * cos(0.5*(lat2+lat1)) 
y = (lat2 - lat1) 
d = R * sqrt( x*x + y*y ) 

我的问题是,对于 lat1 和 lon1 的用户输入,我将如何计算 lat1 lon1 和 lat2 lon2 之间的所有距离(其中 lat2 lon2 将采用 json 文件中所有 5000 lat/lon 的值),然后打印最低的5个距离?

我曾考虑过使用 list.sort,但不确定如何使用 python 计算所有 5000 个距离。

非常感谢。

编辑:

使用 Eric Duminil 提供的代码,以下代码可以满足我的需要。

from math import cos, sqrt
import sys
import json
busstops = json.loads(open("stops.json").read())
R = 6371000 #radius of the Earth in m 
def distance(lon1, lat1, lon2, lat2): 
  x = (lon2-lon1) * cos(0.5*(lat2+lat1)) 
  y = (lat2-lat1) 
  return R * sqrt( x*x + y*y )
buslist = sorted(busstops, key= lambda d: distance(d["Longitude"], d["Latitude"], 103.5, 1.2))
print(buslist[:5])

其中 103.5, 1.2 from buslist 是用户输入经度纬度的示例。

【问题讨论】:

  • 看看pypi.python.org/pypi/geopy。你可能会找到一种方法来获得某种方式。另请查看此评论stackoverflow.com/a/19412565/6165783
  • 感谢您的链接。但是,我并不关心 2 lat/lon 之间距离的计算,而是 - 对于给定 lat/lon 的用户,我如何使用包含 5000 个公交车站的 json 文件找到最近的 5 个公交车站。
  • 抱歉,如果我的问题表述不好

标签: python json python-3.x


【解决方案1】:

您可以简单地定义一个函数来计算距离,并使用它通过 key 参数对公交车站进行排序:

from math import cos, sqrt, pi

R = 6371000 #radius of the Earth in m
def distance(lon1, lat1, lon2, lat2):
    x = (lon2 - lon1) * cos(0.5*(lat2+lat1))
    y = (lat2 - lat1)
    return (2*pi*R/360) * sqrt( x*x + y*y )

bustops = [{"BusStopCode": "00481", "RoadName": "Woodlands Rd", "Description": "BT PANJANG TEMP BUS PK", "Latitude": 1.383764, "Longitude": 103.7583},
{"BusStopCode": "01012", "RoadName": "Victoria St", "Description": "Hotel Grand Pacific", "Latitude": 1.29684825487647, "Longitude": 103.85253591654006}]

print(sorted(bustops, key= lambda d: distance(d["Longitude"], d["Latitude"], 103.5, 1.2)))
# [{'BusStopCode': '01012', 'RoadName': 'Victoria St', 'Description': 'Hotel Grand Pacific', 'Latitude': 1.29684825487647, 'Longitude': 103.85253591654006}, {'BusStopCode': '00481', 'RoadName': 'Woodlands Rd', 'Description': 'BT PANJANG TEMP BUS PK', 'Latitude': 1.383764, 'Longitude': 103.7583}]

排序此列表后,您可以使用[:5] 简单地提取最近的 5 个巴士站。 它应该足够快,即使有 5000 个公交车站。

请注意,如果您不关心具体距离,而只想对公交车站进行排序,则可以将此功能用作键:

def distance2(lon1, lat1, lon2, lat2):
    x = (lon2 - lon1) * cos(0.5*(lat2+lat1))
    y = (lat2 - lat1)
    return x*x + y*y

【讨论】:

  • 谢谢,这正是我所需要的。但是,当我尝试 [:5] 时,出现以下错误:'NoneType' 对象不可下标
  • 已更改代码和工作(参考问题帖子)
【解决方案2】:

我为这样的项目做了同样的事情,但是计算大型数据集的所有距离可能需要很多时间。

我最终得到了knn nearest neighbors,它要快得多,而且你不需要一直重新计算距离:

import numpy as np
from sklearn.neighbors import NearestNeighbors

buslist = [{ ...., 'latitude':45.5, 'longitude':7.6}, { ...., 'latitude':48.532, 'longitude':7.451}]

buslist_coords = np.array([[x['latitude'], x['longitude']] for x in buslist]) #extracting x,y coordinates

# training the knn with the xy coordinates
knn = NearestNeighbors(n_neighbors=num_connections)
knn.fit(buslist_coords)
distances, indices = knn.kneighbors(xy_coordinates)
# you can pickle these and load them later to determinate the nearest point to an user


# finding the nearest point for a given coordinate
userlocation = [47.456, 6.25]
userlocation = np.array([[userlocation[0], userlocation[1]]])
distances, indices = knn.kneighbors(userlocation)

# get the 5 nearest stations in a list
nearest_stations = buslist[indices[0][:5]] # the order of the buslist must be the same when training the knn and finding the nearest point

# printing the 5 nearest stations
for station in nearest_stations :
    print(station)

之后,我用这些数据用 networkx 构建了一个图表,但我仍然使用 knn.kneighbors(userlocation) 来查找用户的最近点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    相关资源
    最近更新 更多