Scipy: 如何将 KD-Tree 距离从查询转换为公里 (Python/Pandas)
Scipy: how to convert KD-Tree distance from query to kilometers (Python/Pandas)
这个 post 建立在 的基础上。
我得到了一个 Pandas 数据框,其中包含城市及其地理坐标(大地测量)作为经度和纬度。
import pandas as pd
df = pd.DataFrame([{'city':"Berlin", 'lat':52.5243700, 'lng':13.4105300},
{'city':"Potsdam", 'lat':52.3988600, 'lng':13.0656600},
{'city':"Hamburg", 'lat':53.5753200, 'lng':10.0153400}]);
对于每个城市,我试图找到另外两个最近的城市。因此我尝试了scipy.spatial.KDTree。为此,我必须将大地坐标转换为 3D catesian 坐标(ECEF = earth-centered, earth-fixed):
from math import *
def to_Cartesian(lat, lng):
R = 6367 # radius of the Earth in kilometers
x = R * cos(lat) * cos(lng)
y = R * cos(lat) * sin(lng)
z = R * sin(lat)
return x, y, z
df['x'], df['y'], df['z'] = zip(*map(to_Cartesian, df['lat'], df['lng']))
df
给我这个:
有了这个我可以创建 KDTree:
coordinates = list(zip(df['x'], df['y'], df['z']))
from scipy import spatial
tree = spatial.KDTree(coordinates)
tree.data
现在我正在柏林进行测试,
tree.query(coordinates[0], 2)
这正确地将柏林(本身)和波茨坦作为我列表中距离柏林最近的两个城市。
问题:但我想知道如何处理该查询的距离?它说 1501 - 但我如何将其转换为米或公里?柏林到波茨坦的实际距离是27公里,而不是1501公里。
备注:我知道我可以得到两个城市的longitude/latitude并计算半正弦距离。但是使用 KDTree 的输出会很酷。
(array([ 0. , 1501.59637685]), array([0, 1]))
感谢任何帮助。
KDTree正在计算两点(城市)之间的欧氏距离。两座城市与地心形成isosceles triangle.
德语维基百科条目包含对英语条目缺少的 geometric properties 的很好概述。您可以使用它来计算距离。
import numpy as np
def deg2rad(degree):
rad = degree * 2*np.pi / 360
return(rad)
def distToKM(x):
R = 6367 # earth radius
gamma = 2*np.arcsin(deg2rad(x/(2*R))) # compute the angle of the isosceles triangle
dist = 2*R*sin(gamma/2) # compute the side of the triangle
return(dist)
distToKM(1501.59637685)
# 26.207800812050056
更新
在关于获得相反的评论之后我重新阅读了问题并意识到虽然似乎可以使用上面提出的功能,但真正的问题在于其他地方。
cos
和 sin
在你的函数中 to_Cartesian
期望输入在 radians
(documentation) 而你把角度交给他们程度。您可以使用上面定义的函数 deg2rad
将纬度和经度转换为弧度。这应该给你直接从 KDTree 到 km 的距离。
这个 post 建立在
我得到了一个 Pandas 数据框,其中包含城市及其地理坐标(大地测量)作为经度和纬度。
import pandas as pd
df = pd.DataFrame([{'city':"Berlin", 'lat':52.5243700, 'lng':13.4105300},
{'city':"Potsdam", 'lat':52.3988600, 'lng':13.0656600},
{'city':"Hamburg", 'lat':53.5753200, 'lng':10.0153400}]);
对于每个城市,我试图找到另外两个最近的城市。因此我尝试了scipy.spatial.KDTree。为此,我必须将大地坐标转换为 3D catesian 坐标(ECEF = earth-centered, earth-fixed):
from math import *
def to_Cartesian(lat, lng):
R = 6367 # radius of the Earth in kilometers
x = R * cos(lat) * cos(lng)
y = R * cos(lat) * sin(lng)
z = R * sin(lat)
return x, y, z
df['x'], df['y'], df['z'] = zip(*map(to_Cartesian, df['lat'], df['lng']))
df
给我这个:
有了这个我可以创建 KDTree:
coordinates = list(zip(df['x'], df['y'], df['z']))
from scipy import spatial
tree = spatial.KDTree(coordinates)
tree.data
现在我正在柏林进行测试,
tree.query(coordinates[0], 2)
这正确地将柏林(本身)和波茨坦作为我列表中距离柏林最近的两个城市。
问题:但我想知道如何处理该查询的距离?它说 1501 - 但我如何将其转换为米或公里?柏林到波茨坦的实际距离是27公里,而不是1501公里。
备注:我知道我可以得到两个城市的longitude/latitude并计算半正弦距离。但是使用 KDTree 的输出会很酷。
(array([ 0. , 1501.59637685]), array([0, 1]))
感谢任何帮助。
KDTree正在计算两点(城市)之间的欧氏距离。两座城市与地心形成isosceles triangle.
德语维基百科条目包含对英语条目缺少的 geometric properties 的很好概述。您可以使用它来计算距离。
import numpy as np
def deg2rad(degree):
rad = degree * 2*np.pi / 360
return(rad)
def distToKM(x):
R = 6367 # earth radius
gamma = 2*np.arcsin(deg2rad(x/(2*R))) # compute the angle of the isosceles triangle
dist = 2*R*sin(gamma/2) # compute the side of the triangle
return(dist)
distToKM(1501.59637685)
# 26.207800812050056
更新
在关于获得相反的评论之后我重新阅读了问题并意识到虽然似乎可以使用上面提出的功能,但真正的问题在于其他地方。
cos
和 sin
在你的函数中 to_Cartesian
期望输入在 radians
(documentation) 而你把角度交给他们程度。您可以使用上面定义的函数 deg2rad
将纬度和经度转换为弧度。这应该给你直接从 KDTree 到 km 的距离。