在计算地球上各点之间的距离时,为什么我的 Haversine 与 Geodesic 计算结果不同?
When calcuating distance between points on earth why are my Haversine vs. Geodesic calculations diverging?
我使用两个近似值来计算地球表面各点之间的距离,得到的距离大相径庭。我正在使用 Haversine (vectorized) approximation and the more precise (presumably) geopy.distance.geodesic 。
如您所见,随着点之间的距离变大,我偏离了百分之五。这种分歧是由于 Haversine 中的舍入误差造成的吗?我真的相信测地线吗?这是代码:
import numpy as np
lat = np.linspace(35,45,100)
lon = np.linspace(-120,-110,100)
data = pd.DataFrame({'Latitude':lat,'Longitude':lon})
def Haversine(v):
"""
distance between two lat,lon coordinates
using the Haversine formula. Assumes one
radius. r = 3,950 to 3,963 mi
"""
from timeit import default_timer as timer
start = timer()
R = 3958 # radius at 40 deg 750 m elev
v = np.radians(v)
dlat = v[:, 0, np.newaxis] - v[:, 0]
dlon = v[:, 1, np.newaxis] - v[:, 1]
c = np.cos(v[:,0,None])
a = np.sin(dlat / 2.0) ** 2 + c * c.T * np.sin(dlon / 2.0) ** 2
c = 2 * np.arcsin(np.sqrt(a))
result = R * c
print(round((timer() - start),3))
return result
def slowdistancematrix(data):
from geopy.distance import geodesic
distance = np.zeros((data.shape[0],data.shape[0]))
for i in range(data.shape[0]):
lat_lon_i = data.Latitude.iloc[i],data.Longitude.iloc[i]
for j in range(i):
lat_lon_j = data.Latitude.iloc[j],data.Longitude.iloc[j]
distance[i,j] = geodesic(lat_lon_i, lat_lon_j).miles
distance[j,i] = distance[i,j] # make use of symmetry
return distance
distanceG = slowdistancematrix(data)
distanceH = Haversine(data.values)
plt.scatter(distanceH.ravel(),distanceG.ravel()/distanceH.ravel(),s=.5)
plt.ylabel('Geodesic/Haversine')
plt.xlabel('Haversine distance (miles)')
plt.title('all points in distance matrix')
我宁愿使用矢量化版本,因为它速度很快。然而,5% 太大了,我无法接受。假设 Haversine 仅假设偏离 0.5%。
更新:
发现错误。在实现矢量化版本时,我并没有计算点之间的所有距离,而是只计算了一些点之间的距离。我更新了代码以反映这一点。以下是我的域的 Haversine 和 Geodesic 之间的区别(25-55* by -125--110):
非常好!
Haversine 公式计算 sphere 上各点之间的距离(大圆距离),geopy.distance.great_circle
.
也是如此
另一方面,geopy.distance.geodesic
计算地球椭圆体模型上点之间的距离,您可以将其视为 "flattened" 球体。
差异不是因为四舍五入,而是因为它们使用了不同的公式,测地线公式更准确地模拟了地球的真实形状。
Haversine 公式中存在矩阵代数错误。我更新了问题中的代码。我现在在 Haversine 和测地线之间取得了更好的一致:
在我的实际数据集上:
我使用两个近似值来计算地球表面各点之间的距离,得到的距离大相径庭。我正在使用 Haversine (vectorized) approximation and the more precise (presumably) geopy.distance.geodesic 。
如您所见,随着点之间的距离变大,我偏离了百分之五。这种分歧是由于 Haversine 中的舍入误差造成的吗?我真的相信测地线吗?这是代码:
import numpy as np
lat = np.linspace(35,45,100)
lon = np.linspace(-120,-110,100)
data = pd.DataFrame({'Latitude':lat,'Longitude':lon})
def Haversine(v):
"""
distance between two lat,lon coordinates
using the Haversine formula. Assumes one
radius. r = 3,950 to 3,963 mi
"""
from timeit import default_timer as timer
start = timer()
R = 3958 # radius at 40 deg 750 m elev
v = np.radians(v)
dlat = v[:, 0, np.newaxis] - v[:, 0]
dlon = v[:, 1, np.newaxis] - v[:, 1]
c = np.cos(v[:,0,None])
a = np.sin(dlat / 2.0) ** 2 + c * c.T * np.sin(dlon / 2.0) ** 2
c = 2 * np.arcsin(np.sqrt(a))
result = R * c
print(round((timer() - start),3))
return result
def slowdistancematrix(data):
from geopy.distance import geodesic
distance = np.zeros((data.shape[0],data.shape[0]))
for i in range(data.shape[0]):
lat_lon_i = data.Latitude.iloc[i],data.Longitude.iloc[i]
for j in range(i):
lat_lon_j = data.Latitude.iloc[j],data.Longitude.iloc[j]
distance[i,j] = geodesic(lat_lon_i, lat_lon_j).miles
distance[j,i] = distance[i,j] # make use of symmetry
return distance
distanceG = slowdistancematrix(data)
distanceH = Haversine(data.values)
plt.scatter(distanceH.ravel(),distanceG.ravel()/distanceH.ravel(),s=.5)
plt.ylabel('Geodesic/Haversine')
plt.xlabel('Haversine distance (miles)')
plt.title('all points in distance matrix')
我宁愿使用矢量化版本,因为它速度很快。然而,5% 太大了,我无法接受。假设 Haversine 仅假设偏离 0.5%。
更新:
发现错误。在实现矢量化版本时,我并没有计算点之间的所有距离,而是只计算了一些点之间的距离。我更新了代码以反映这一点。以下是我的域的 Haversine 和 Geodesic 之间的区别(25-55* by -125--110):
非常好!
Haversine 公式计算 sphere 上各点之间的距离(大圆距离),geopy.distance.great_circle
.
另一方面,geopy.distance.geodesic
计算地球椭圆体模型上点之间的距离,您可以将其视为 "flattened" 球体。
差异不是因为四舍五入,而是因为它们使用了不同的公式,测地线公式更准确地模拟了地球的真实形状。
Haversine 公式中存在矩阵代数错误。我更新了问题中的代码。我现在在 Haversine 和测地线之间取得了更好的一致:
在我的实际数据集上: