【问题标题】:Faster approach to finding distance between coordinates更快的方法来查找坐标之间的距离
【发布时间】:2021-05-19 20:41:53
【问题描述】:

我有一个地点列表,我需要找出每个地点之间的距离。谁能建议一种更快的方法?大约有 10k 个独特的位置,我使用的方法创建了一个 10k X 10k 矩阵,但内存不足。我使用的是 15GB 内存。

    test_df

   Latitude  Longitude  site
    0   32.3    -94.1   1
    1   35.2    -93.1   2
    2   33.1    -83.4   3
    3   33.2    -94.5   4
test_df = test_df[['site', 'Longitude', 'Latitude']]    
test_df['coord'] = list(zip(test_df['Longitude'], test_df['Latitude']))
from haversine import haversine
for _,row in test_df.iterrows():
    test_df[row.coord]=round(test_df['coord'].apply(lambda x:haversine(row.coord,x, unit='mi')),2)
df = test_df.rename(columns=dict(zip(test_df['coord'], test_df['Facility'])))
df.drop('coord', axis=1, inplace=True)
new_df = pd.melt(df, id_vars='Facility', value_vars=df.columns[1:])
new_df.rename(columns={'variable':'Place', 'value':'dist_in_mi'}, inplace=True)
new_df


 site Place dist_in_mi
0   1   1   0.00
1   2   1   70.21
2   3   1   739.28
3   4   1   28.03
4   1   2   70.21
5   2   2   0.00
6   3   2   670.11
7   4   2   97.15
8   1   3   739.28
9   2   3   670.11
10  3   3   0.00
11  4   3   766.94
12  1   4   28.03
13  2   4   97.15
14  3   4   766.94
15  4   4   0.00

【问题讨论】:

  • 我们能否将数据框设为可复制粘贴的形式(例如托管在 github 上)?
  • 您要求更快的方法,但您说问题是内存不足
  • 你说得对,我需要一个更快的方法,因为我使用它的方式没有经过优化 - 我尝试使用我在这里共享的虚拟集,它有效
  • 为了更快的方法,我建议使用多处理并且不要计算与同一地点的距离 2 次​​span>

标签: python pandas haversine


【解决方案1】:

如果您想解决内存问题,您需要使用使用较少内存的数据类型。 在这种情况下,由于地球上两点之间的最大距离小于20005Km,您可以使用uint16 来存储该值(如果 1Km 分辨率对您来说足够了)

由于我没有任何数据可以使用,我使用以下代码生成了一些数据:

import random

import numpy as np
from haversine import haversine

def getNFacilities(n):
    """ returns n random pairs of coordinates in the range [-90, +90]"""
    for i in range(n):
        yield random.random()*180 - 90, random.random()*180 - 90

facilities = list(getNFacilities(10000))

然后我用两种不同的方式解决了内存问题:

1- 通过将距离数据存储在uint16 数字中

def calculateDistance(start, end):
    mirror = start is end # if the matrix is mirrored the values are calculated just one time instead of two
    out = np.zeros((len(start), len(end)), dtype = np.uint16) # might be better to use empty?
    for i, coords1 in enumerate(start[mirror:], mirror):
        for j, coords2 in enumerate(end[:mirror and i or None]):
            out[i, j] = int(haversine(coords1, coords2))
    return out

计算距离后数组使用的内存约为200MB:

In [133]: l = calculateDistance(facilities, facilities)

In [134]: sys.getsizeof(l)
Out[134]: 200000112

2- 或者,您可以只使用生成器:

def calculateDistance(start, end):
    mirror = start is end # if the matrix is mirrored the values are calculated just one time
    for i, coords1 in enumerate(start[mirror:], mirror):
        for j, coords2 in enumerate(end[:mirror and i or None]):
            yield [i, j, haversine(coords1, coords2)]

【讨论】:

  • 使用生成器方法,当我使用 for..loop 读取数据帧时,它再次耗尽内存,有什么建议吗?
  • 生成器非常适合“动态”计算,例如。找到设施之间的平均距离,但如果您需要将值存储在 ram 中,第一种方法可能会更好
  • 或者您可以在这里查看一些处理大型数据集的方法:pandas.pydata.org/pandas-docs/stable/user_guide/…
猜你喜欢
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 2021-10-11
  • 2022-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多