python - 使用纬度/经度计算距离矩阵的更快方法

标签 python pandas numpy distance

我正在使用纬度/经度填充一个大距离矩阵(n=5000),并且正在寻找一种更快的方法来做到这一点。

示例代码

import pandas as pd
import numpy as np

# Calculate distance lat/long (Thanks @Jamie)
def spherical_dist(pos1, pos2, r=3958.75):
    pos1 = np.array(pos1)
    pos2 = np.array(pos2)
    pos1 = pos1 * np.pi / 180
    pos2 = pos2 * np.pi / 180
    cos_lat1 = np.cos(pos1[..., 0])
    cos_lat2 = np.cos(pos2[..., 0])
    cos_lat_d = np.cos(pos1[..., 0] - pos2[..., 0])
    cos_lon_d = np.cos(pos1[..., 1] - pos2[..., 1])
    return r * np.arccos(cos_lat_d - cos_lat1 * cos_lat2 * (1 - cos_lon_d))

# Emtpy dataframe
dat = pd.DataFrame({'id': ['a', 'b', 'c', 'd'], 'lat': [-20, -21, -22, -24], 'lon': [-100, -101, -102, -103]})
dist_mat = pd.DataFrame(0, index=dat.id, columns=dat.id)
dist_mat

# Populate
for i in range(4):
    for j in range(4):
        dist_mat.iloc[i, j] = spherical_dist([dat.iloc[i, 1], dat.iloc[i, 2]], [dat.iloc[j, 1], dat.iloc[j, 2]])

输出

> dist_mat

id  a   b   c   d
id              
a   0.000000    94.668315   189.039530  336.591787
b   94.668315   0.000000    94.373392   243.429659
c   189.039530  94.373392   0.000000    152.118003
d   336.591787  243.429659  152.118003  0.000000

最佳答案

使用库 geopy 计算距离的另一种解决方案:

from geopy.distance import lonlat, distance, great_circle

df = pd.DataFrame({'id': ['a', 'b', 'c', 'd'], 'lat': [-20, -21, -22, -24], 'lon': [-100, -101, -102, -103]}) 

#using merge to generate all possibilities between origin and destination 
df= pd.merge(df.assign(key=0), df.assign(key=0),suffixes=('', '_x') , on='key').drop('key', axis=1)

#using the library geopy to gives the distance between 2 points
df['Miles'] = df.apply(
    (lambda row:distance(lonlat(row['lon'], row['lat']),
                         lonlat(row['lon_x'], row['lat_x'])).miles), axis=1)

#create the crosstab
df = df.groupby(['id', 'id_x'])['Miles'].max().unstack()
print(df)

使用度量测地线计算距离的输出(默认): 距离()=测地线()

id_x           a           b           c           d
id                                                  
a       0.000000   94.516982  188.743084  335.820435
b      94.516982    0.000000   94.228293  242.812242
c     188.743084   94.228293    0.000000  151.653020
d     335.820435  242.812242  151.653020    0.000000

使用度量great_circle计算距离的输出:这似乎是你的做法

df['Miles'] = df.apply(
    (lambda row:great_circle(lonlat(row['lon'], row['lat']),
                         lonlat(row['lon_x'], row['lat_x'])).miles), axis=1)

id_x           a           b           c           d
id                                                  
a       0.000000   94.668589  189.040078  336.592761
b      94.668589    0.000000   94.373665  243.430364
c     189.040078   94.373665    0.000000  152.118443
d     336.592761  243.430364  152.118443    0.000000

您可以将度量单位“英里”更改为“公里”,只需将 distance() 或 Great_circle() 中的扩展名从 .miles 更改为 .km

关于python - 使用纬度/经度计算距离矩阵的更快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55055276/

相关文章:

python-2.7 - 使用python查找数据框中序列重复的次数

python - 无法将 pip3 与 sudo 一起使用

python - Numpy:每个操作的内存分配?

python - 我想在 django 社交应用登录后添加自定义字段

python - 如果变量包含的只是数字,如何知道变量是分类变量还是数值变量?

python - 在 pandas 列中将不同的工资类型(每年、每月等)转换为每月

python - 如何处理 Pandas 中的 2 列并使用新列名称创建新数据框

python - 同时有效地获取 numpy.argmin 和 numpy.amin

python - 多线程Python应用程序的远程调试

python - 合并具有非唯一索引的多个数据帧