python - 成对的 haversine 距离计算

标签 python arrays performance numpy haversine

我有两个包含纬度和经度的数组。我想计算数组中每一对纬度和经度与其他每一对纬度和经度之间的距离。 这是我的两个数组。

lat_array

array([ 0.33356456,  0.33355585,  0.33355585,  0.33401788,  0.33370132,
        0.33370132,  0.33370132,  0.33371075,  0.33371075,  0.33370132,
        0.33370132,  0.33370132,  0.33356488,  0.33356488,  0.33370132,
        0.33370132,  0.33370132,  0.33401788,  0.33362632,  0.33362632,
        0.33364007,  0.33370132,  0.33401788,  0.33401788,  0.33358399,
        0.33358399,  0.33358399,  0.33370132,  0.33370132,  0.33362632,
        0.33370132,  0.33370132,  0.33370132,  0.33370132,  0.33370132,
        0.33356488,  0.33356456,  0.33391071,  0.33370132,  0.33356488,
        0.33356488,  0.33356456,  0.33356456,  0.33356456,  0.33362632,
        0.33364804,  0.3336314 ,  0.33370132,  0.33370132,  0.33370132,
        0.33364034,  0.33359921,  0.33370132,  0.33360397,  0.33348863,
        0.33370132])
long_array

array([ 1.27253229,  1.27249141,  1.27249141,  1.27259085,  1.2724337 ,
        1.2724337 ,  1.2724337 ,  1.27246931,  1.27246931,  1.2724337 ,
        1.2724337 ,  1.2724337 ,  1.27254305,  1.27254305,  1.2724337 ,
        1.2724337 ,  1.2724337 ,  1.27259085,  1.27250461,  1.27250461,
        1.27251211,  1.2724337 ,  1.27259085,  1.27259085,  1.27252134,
        1.27252134,  1.27252134,  1.2724337 ,  1.2724337 ,  1.27250461,
        1.2724337 ,  1.2724337 ,  1.2724337 ,  1.2724337 ,  1.2724337 ,
        1.27254305,  1.27253229,  1.27266808,  1.2724337 ,  1.27254305,
        1.27254305,  1.27253229,  1.27253229,  1.27253229,  1.27250461,
        1.27250534,  1.27250184,  1.2724337 ,  1.2724337 ,  1.2724337 ,
        1.27251339,  1.27223739,  1.2724337 ,  1.2722575 ,  1.27237575,
        1.2724337 ])

转换成弧度后。现在我想要第一对纬度和经度与剩余的纬度和经度对之间的距离等等。并想打印对和相应的距离。

这就是我在 python 中所做的。

distance = []
R = 6371.0

for i in range(len(lat_array)):
   for j in (i+1,len(lat_array)):
      dlon = long_array[j]-long_array[i]
      dlat = lat_array[j]-lat_array[i]
      a = sin(dlat / 2)**2 + cos(lat_array[i]) * cos(lat_array[j]) *     
          sin(dlon / 2)**2
      c = 2 * atan2(sqrt(a), sqrt(1 - a))

      distance.append(R * c)

它给我一个错误 IndexError: index 56 is out of bounds for axis 0 with size 56 我哪里做错了?如果数组很大,如何使计算更快?请帮忙。

最佳答案

由于这是目前 Google 在“成对 haversine 距离”方面的最高结果,我要补充两分钱:如果您可以访问 scikit-learn,这个问题可以很快得到解决。查看 sklearn.metrics.pairwise_distances 时,您会注意到不支持“haversine”指标,但它在 sklearn.neighbors.DistanceMetric 中实现。

这意味着您可以执行以下操作:

from sklearn.neighbors import DistanceMetric

def sklearn_haversine(lat, lon):
    haversine = DistanceMetric.get_metric('haversine')
    latlon = np.hstack((lat[:, np.newaxis], lon[:, np.newaxis]))
    dists = haversine.pairwise(latlon)
    return 6371 * dists

请注意,latlon 的串联是必需的,因为它们是单独的数组。如果您将它们作为 (n_samples, 2) 形状的组合数组传递,您可以直接在它们上调用 haversine.pairwise。此外,仅当您需要以公里为单位的距离时,才需要乘以 6371。例如。如果您只想找到最近的一对点,则不需要此步骤。

验证:

In [87]: lat = np.array([ 0.33356456,  0.33355585,  0.33355585,  0.33401788,  0.33370132])

In [88]: lng = np.array([ 1.27253229,  1.27249141,  1.27249141,  1.27259085,  1.2724337 ])

In [89]: sklearn_haversine(lat, lng)
Out[89]:
array([[ 0.        ,  0.25227021,  0.25227021,  2.90953323,  1.05422047],
       [ 0.25227021,  0.        ,  0.        ,  3.00383463,  0.98975923],
       [ 0.25227021,  0.        ,  0.        ,  3.00383463,  0.98975923],
       [ 2.90953323,  3.00383463,  3.00383463,  0.        ,  2.2276139 ],
       [ 1.05422047,  0.98975923,  0.98975923,  2.2276139 ,  0.        ]])

性能:

In [91]: lat = np.random.randn(1000)

In [92]: lng = np.random.randn(1000)

In [93]: %timeit original_app(lat,lng)
1 loops, best of 3: 1.46 s per loop

In [94]: %timeit vectorized_app1(lat,lng)
10 loops, best of 3: 86.7 ms per loop

In [95]: %timeit vectorized_app2(lat,lng)
10 loops, best of 3: 75.7 ms per loop

In [96]: %timeit sklearn_haversine(lat,lng)
10 loops, best of 3: 76 ms per loop

总而言之,您可以用更短更简单的代码以 vectorized_app2 的速度获得 Divakar 的 vectorized_app1 的输出。

关于python - 成对的 haversine 距离计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34557898/

相关文章:

javascript - 获取数字的每一位数字

c# - 尝试捕捉性能

python - 如何使用 BeautifulSoup 在两个不同的标签之间获取值(value)?

php - 表单 - 从 Controller 传递数组到 View - PHP - Laravel

python - 在ubuntu中使用Python显示目录内容

java - 收到错误消息,提示我的数组大小

JavaScript 字符串转化为多维数组

php - 使用 php 和 mysql 构建网站的更有效方法(兑现还是查询?)

python - 如何将随机森林中选定的特征转换为新列表

python - 将惰性求值转换为装饰器 (Python)