【发布时间】:2021-07-31 18:27:45
【问题描述】:
这是我的数据集: https://pastebin.com/SsuKP2eH
我正在尝试为数据集中的所有点找到最近的点。这些点是地球表面的纬度和经度。当然,最近的点不能是同一个点。
我尝试了这篇帖子中列出的KDTree 解决方案:https://stackoverflow.com/a/45128643,并将海报的随机点(由np.random.uniform 生成)更改为我自己的数据集。
我希望得到一个充满距离的数组,但相反,我得到了一个充满零的数组,其中包含一些数字,例如 2.87722e-06 和 0.616582。这不是我想要的。我在我的数据集上尝试了另一个解决方案NearestNeighbours,得到了相同的结果。于是,我做了一些调试,缩小了他使用的随机数的范围,使其更接近我自己的数据集。
import numpy as np
import scipy.spatial as spatial
import pandas as pd
R = 6367
def using_kdtree(data):
"Based on https://stackoverflow.com/q/43020919/190597"
def dist_to_arclength(chord_length):
"""
https://en.wikipedia.org/wiki/Great-circle_distance
Convert Euclidean chord length to great circle arc length
"""
central_angle = 2*np.arcsin(chord_length/(2.0*R))
arclength = R*central_angle
return arclength
phi = np.deg2rad(data['Latitude'])
theta = np.deg2rad(data['Longitude'])
data['x'] = R * np.cos(phi) * np.cos(theta)
data['y'] = R * np.cos(phi) * np.sin(theta)
data['z'] = R * np.sin(phi)
tree = spatial.KDTree(data[['x', 'y','z']])
distance, index = tree.query(data[['x', 'y','z']], k=2)
return dist_to_arclength(distance[:, 1])
#return distance, index
np.random.seed(2017)
N = 1000
#data = pd.DataFrame({'Latitude':np.random.uniform(-90,90,size=N), 'Longitude':np.random.uniform(0, 360,size=N)})
data = pd.DataFrame({'Latitude':np.random.uniform(-49.19,49.32,size=N), 'Longitude':np.random.uniform(-123.02, -123.23,size=N)})
result = using_kdtree(data)
我发现结果距离数组的值很小,接近于 0。这让我相信我的数据集的结果数组充满零的原因是因为点之间的差异非常小。 某处,KD 树/最近邻会丢失精度并输出垃圾。有没有办法让它们保持我的浮点数的精度? 蛮力方法可以保持精度,但它太慢了,需要 7200 个点来迭代。
【问题讨论】:
-
粗体的说法是完全错误的。
-
找到一组可疑点,并为它们手动计算(例如通过调试器)
-
K.,你的精确度是假的。你怎么能假装在地理环境中以 0.1 nm 的精度测量距离?此外,当您使用这些 精确 数字来计算 x, y, z 坐标(用于微观位置差异!)时,精度必然会降低。所以,即使你认为所有的点都是不同的,在 x, y, z 空间中,很多点都被折叠了。我使用板卡雷将您的坐标转换为地图坐标,并且无数个点折叠到相同的位置。我明白我说的不是你想听的,但是……
-
让我们继续,我的建议:①使用Plate Carrée(它是一个正方形,15km×15km,PC足够好)来投影你的点②将位置四舍五入到合理的位数,反映您测量的真实准确度 ③ 创建一个丢弃重复项的新数组 ④ 将完整数组中的重复索引保存在字典中,索引在修剪数组中的位置⑤ 在剪枝后的数组上使用 kdtree,得到的是最近 cluster 个 dat 点的索引。