当前位置:  开发笔记 > 编程语言 > 正文

成对的半径距离计算

如何解决《成对的半径距离计算》经验,为你挑选了2个好方法。

我有两个lat和long数组.我想计算每对lat和long之间的距离,以及阵列中每隔一对lat和long.这是我的两个数组.

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 ])

转换成弧度后.现在我想要第一对lat和long之间的距离以及剩余的lat和long对等等.并希望打印对和相应的距离.

这就是我在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 我在哪里做错了?如果阵列很大,如何使计算更快?请帮忙.



1> jdoerrie..:

由于这是Google目前“成对的hasversine距离”的最高结果,因此我加两分:如果您可以访问,则可以很快解决此问题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

总之,你可以得到Divakar的输出vectorized_app1用的速度vectorized_app2在更短的和简单的代码。



2> Divakar..:

假设lat并且lng作为晶格和经度阵列以及那些具有弧度数据的数据,这里是基于以下的一个矢量化解决方案 this other solution-

# Elementwise differentiations for lattitudes & longitudes
dflat = lat[:,None] - lat
dflng = lng[:,None] - lng

# Finally Calculate haversine using its distance formula
d = np.sin(dflat/2)**2 + np.cos(lat[:,None])*np.cos(lat) * np.sin(dflng/2)**2
hav_dists = 2 * 6371 * np.arcsin(np.sqrt(d))

现在,上述方法将为所有对提供输出,而不管它们的顺序如何.因此,对于两对,我们将有两个距离输出:(point1,point2)&(point2,point1),即使距离相同.因此,为了节省内存并希望获得更好的性能,您可以创建唯一的配对ID np.triu_indices并修改之前列出的方法,如下所示 -

# Elementwise differentiations for lattitudes & longitudes, 
# but not repeat for the same paired elements
N = lat.size
idx1,idx2 = np.triu_indices(N,1)
dflat = lat[idx2] - lat[idx1]
dflng = lng[idx2] - lng[idx1]

# Finally Calculate haversine using its distance formula
d = np.sin(dflat/2)**2 + np.cos(lat[idx2])*np.cos(lat[idx1]) * np.sin(dflng/2)**2
hav_dists = 2 * 6371 * np.arcsin(np.sqrt(d))

功能定义 -

def original_app(lat,lng):
    distance = []
    R = 6371.0
    for i in range(len(lat)):
       for j in range(i+1,len(lat)):
          dlon = lng[j]-lng[i]
          dlat = lat[j]-lat[i]
          a = sin(dlat / 2)**2 + cos(lat[i]) * cos(lat[j]) * sin(dlon / 2)**2
          c = 2 * atan2(sqrt(a), sqrt(1 - a))
          distance.append(R * c)
    return distance

def vectorized_app1(lat,lng):                               
    dflat = lat[:,None] - lat
    dflng = lng[:,None] - lng
    d = np.sin(dflat/2)**2 + np.cos(lat[:,None])*np.cos(lat) * np.sin(dflng/2)**2
    return 2 * 6371 * np.arcsin(np.sqrt(d))

def vectorized_app2(lat,lng):                               
    N = lat.size
    idx1,idx2 = np.triu_indices(N,1)
    dflat = lat[idx2] - lat[idx1]
    dflng = lng[idx2] - lng[idx1]
    d =np.sin(dflat/2)**2+np.cos(lat[idx2])*np.cos(lat[idx1])*np.sin(dflng/2)**2
    return  2 * 6371 * np.arcsin(np.sqrt(d))

验证输出 -

In [78]: lat
Out[78]: array([ 0.33356456,  0.33355585,  0.33355585,  0.33401788,  0.33370132])

In [79]: lng
Out[79]: array([ 1.27253229,  1.27249141,  1.27249141,  1.27259085,  1.2724337 ])

In [80]: original_app(lat,lng)
Out[80]: 
[0.2522702110418014,
 0.2522702110418014,
 2.909533226553249,
 1.0542204712876762,
 0.0,
 3.003834632906676,
 0.9897592295963831,
 3.003834632906676,
 0.9897592295963831,
 2.2276138997714474]

In [81]: vectorized_app1(lat,lng)
Out[81]: 
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 [82]: vectorized_app2(lat,lng)
Out[82]: 
array([ 0.25227021,  0.25227021,  2.90953323,  1.05422047,  0.        ,
        3.00383463,  0.98975923,  3.00383463,  0.98975923,  2.2276139 ])

运行时测试 -

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

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

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

In [86]: %timeit vectorized_app1(lat,lng)
1 loops, best of 3: 263 ms per loop

In [87]: %timeit vectorized_app2(lat,lng)
1 loops, best of 3: 224 ms per loop

因此,为了性能,它似乎vectorized_app2可能是要走的路!

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有