【问题标题】:Vectorised Haversine formula with a pandas dataframe带有熊猫数据框的向量化 Haversine 公式
【发布时间】:2014-11-04 05:32:27
【问题描述】:

我知道要找到两个经纬度点之间的距离,我需要使用haversine函数:

def haversine(lon1, lat1, lon2, lat2):
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    km = 6367 * c
    return km

我有一个数据框,其中一列是纬度,另一列是经度。我想知道这些点离设定点有多远,-56.7213600、37.2175900。如何从 DataFrame 中获取值并将它们放入函数中?

示例数据框:

     SEAZ     LAT          LON
1    296.40,  58.7312210,  28.3774110  
2    274.72,  56.8148320,  31.2923240
3    192.25,  52.0649880,  35.8018640
4     34.34,  68.8188750,  67.1933670
5    271.05,  56.6699880,  31.6880620
6    131.88,  48.5546220,  49.7827730
7    350.71,  64.7742720,  31.3953780
8    214.44,  53.5192920,  33.8458560
9      1.46,  67.9433740,  38.4842520
10   273.55,  53.3437310,   4.4716664

【问题讨论】:

  • 我已经发布了一个可以解决您的问题的答案,但我认为它不是最佳的
  • 对于一个小的 df 我的答案是可以的,但对于一个更大的 df 你最好将度数转换为弧度并存储它,然后在整个数据帧上执行计算
  • 我在 df 中有 143 个值,这似乎运作良好。
  • 好的,但通常使用apply 应该是最后的手段,pandas 和 numpy 中有向量化函数将对整个 df 执行数学运算,请检查我不能保证的数字

标签: python pandas haversine


【解决方案1】:

我无法确认计算是否正确,但以下方法有效:

In [11]:

from numpy import cos, sin, arcsin, sqrt
from math import radians

def haversine(row):
    lon1 = -56.7213600
    lat1 = 37.2175900
    lon2 = row['LON']
    lat2 = row['LAT']
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * arcsin(sqrt(a)) 
    km = 6367 * c
    return km

df['distance'] = df.apply(lambda row: haversine(row), axis=1)
df
Out[11]:
         SEAZ        LAT        LON     distance
index                                           
1      296.40  58.731221  28.377411  6275.791920
2      274.72  56.814832  31.292324  6509.727368
3      192.25  52.064988  35.801864  6990.144378
4       34.34  68.818875  67.193367  7357.221846
5      271.05  56.669988  31.688062  6538.047542
6      131.88  48.554622  49.782773  8036.968198
7      350.71  64.774272  31.395378  6229.733699
8      214.44  53.519292  33.845856  6801.670843
9        1.46  67.943374  38.484252  6418.754323
10     273.55  53.343731   4.471666  4935.394528

以下代码在如此小的数据帧上实际上速度较慢,但​​我将其应用于 100,000 行 df:

In [35]:

%%timeit
df['LAT_rad'], df['LON_rad'] = np.radians(df['LAT']), np.radians(df['LON'])
df['dLON'] = df['LON_rad'] - math.radians(-56.7213600)
df['dLAT'] = df['LAT_rad'] - math.radians(37.2175900)
df['distance'] = 6367 * 2 * np.arcsin(np.sqrt(np.sin(df['dLAT']/2)**2 + math.cos(math.radians(37.2175900)) * np.cos(df['LAT_rad']) * np.sin(df['dLON']/2)**2))

1 loops, best of 3: 17.2 ms per loop

相比apply函数耗时4.3s快了近250倍,以后要注意的地方

如果我们将以上所有内容压缩成一个单行:

In [39]:

%timeit df['distance'] = 6367 * 2 * np.arcsin(np.sqrt(np.sin((np.radians(df['LAT']) - math.radians(37.2175900))/2)**2 + math.cos(math.radians(37.2175900)) * np.cos(np.radians(df['LAT'])) * np.sin((np.radians(df['LON']) - math.radians(-56.7213600))/2)**2))
100 loops, best of 3: 12.6 ms per loop

我们观察到现在的速度进一步提高了约 341 倍。

【讨论】:

  • 感谢优化对比。干得好。
  • 从这个链接检查方程:movable-type.co.uk/scripts/latlong.html
  • 在使用 np.arcsin(area) 时应该去掉这个词 np.cos(np.radians(df['LAT'])
  • @AhmadSuliman 抱歉,您能否建议整行应该是什么并解释原因,因为我目前还不清楚为什么
  • @AhmadSuliman 你提议的编辑由于某种原因被拒绝,我试图让你的代码运行,它产生了非常不同的结果。您能否提出代码正确的编辑并提供可验证的样本、数据和结果
猜你喜欢
  • 1970-01-01
  • 2020-07-30
  • 2013-01-22
  • 2015-01-26
  • 2019-03-17
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
  • 2018-02-05
相关资源
最近更新 更多