Scipy:如何将KD-Tree距离从查询转换为公里(Python / Pandas)

时间:2017-03-25 19:25:09

标签: python scipy geospatial spatial kdtree

这篇文章建立在this one之上。

我得到了一个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 =以地球为中心,地球固定):

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

这给我这个:

python output

有了这个我可以创建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公里。

备注:我知道我可以获得两个城市的经度/纬度并计算半径距离。但是使用KDTree的输出会很酷。

  

(array([0。,1501.59637685]),array([0,1]))

感谢任何帮助。

1 个答案:

答案 0 :(得分:4)

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中的

sinto_Cartesian期望输入位于radiansdocumentation),而您正在以度数方式处理它们。您可以使用上面定义的函数deg2rad将纬度和经度转换为弧度。这应该给你直接距离KDTree的距离。