【问题标题】:Finding the closest coordinates to a point寻找离点最近的坐标
【发布时间】:2020-04-19 12:13:13
【问题描述】:

我有城市坐标:(52.2319581, 21.0067249) 和 Python 字典,其中包含提到的城市周围的城市。如何从给定坐标中获取 3 个最近的城市:

({'Brwinów': (52.133333, 20.716667), 'Warszawa Bielany': (52.283333, 20.966667), 'Legionowo': (52.4, 20.966667), 'Warszawa-Okęcie': (52.16039, 20.961674), 'Warszawa': (52.280957, 20.961348), 'Belsk Duży': (51.833333, 20.8)}, {})

感谢您的帮助。

【问题讨论】:

  • 这使用外部库,而这似乎不是 OP 想要的
  • @FarhoodET 我不需要矩阵,只需要 3 个离给定坐标最近的城市。
  • @Bartol 很好地创建了矩阵,然后获得该矩阵中每个城市的前 3 名。无论如何,您必须创建矩阵。
  • 每个人都建议使用欧几里得距离来表示明显的球坐标,当您不靠近赤道时,这是非常错误的。请看great-circle distance!或者,更有可能的是,这些甚至不是球坐标,而是使用球体的 WGS84,但如果可以将整个城市视为一个点,那么这种区别就不太重要了。

标签: python python-3.x data-science


【解决方案1】:

没有任何外部库

from math import acos, cos, sin

def gc_distance(first_point, second_point):
    return acos(sin(first_point[1]) * sin(second_point[1]) + cos(first_point[1]) * cos(second_point[1]) * cos(first_point[0] - second_point[0]))

def three_closest(city, cities):
    cities_distances = { key: gc_distance(city, value) for key, value in cities.items()}
    return [k for k, v in sorted(cities_distances.items(), key=lambda item: item[1])][:3]

样本测试:

>>> city = (52.2319581, 21.0067249)
>>> cities = {'Brwinów': (52.133333, 20.716667), 'Warszawa Bielany': (52.283333, 20.966667), 'Legionowo': (52.4, 20.966667), 'Warszawa-Okęcie': (52.16039, 20.961674), 'Warszawa': (52.280957, 20.961348), 'Belsk Duży': (51.833333, 20.8)}
>>> three_closest(city, cities)
['Warszawa Bielany', 'Warszawa', 'Warszawa-Okęcie']

如果您想返回键和值:

for result in three_closest(city, cities):
    print(result + " : " + str(cities[result]))

获得:

Warszawa Bielany : (52.283333, 20.966667)
Warszawa : (52.280957, 20.961348)
Warszawa-Okęcie : (52.16039, 20.961674)

【讨论】:

【解决方案2】:

对于明显的球坐标,每个人都推荐欧几里得距离,当您不靠近赤道时,这是非常错误的。在示例坐标(波兰)中,大约 52° 纬度:
1° 的纬度仍然约为 10000 公里 / 90° = 111 公里,但是
1° 的经度只有 10000 公里 * cos(52°) / 90° = 68 公里。
所以至少我们必须改用great-circle distance!

from math import sin, cos, acos

def angle(c1, 2):
  l1, p1 = c1
  l2, p2 = c2
  return acos(sin(p1) * sin(p2) + cos(p1) * cos(p2) * cos(l2 - l1))

sorted_coords = sorted(coords, key=lambda city: angle(city, center))
print(sorted_coords[:3])

更有可能的是,这些甚至不是球坐标,而是 WGS84,它使用一个球体,但如果可以将整个城市视为一个点,那么这种区别就不太重要了。

【讨论】:

    【解决方案3】:

    也许这会起作用(这没有考虑到一个经度在不同纬度意味着不同距离的事实)。

    the_city = (52.2319581, 21.0067249)
    cities = ({'Brwinów': (52.133333, 20.716667), 'Warszawa Bielany': (52.283333, 20.966667), 'Legionowo': (52.4, 20.966667), 'Warszawa-Okęcie': (52.16039, 20.961674), 'Warszawa': (52.280957, 20.961348), 'Belsk Duży': (51.833333, 20.8)}, {})
    
    closest3 = sorted(cities[0], key=lambda k: (cities[0][k][0]-the_city[0])**2 + (cities[0][k][1]-the_city[1])**2)[:3]
    

    【讨论】:

    • 这通常不适用于球坐标。它仅在两点相距不太远、不跨越经度 -180 到 180 度的交界处且靠近赤道(与波兰不同)时作为近似值。
    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 2014-09-07
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2018-02-06
    相关资源
    最近更新 更多