【问题标题】:How do I find the closest point for each point in a data set while keeping precision?如何在保持精度的同时找到数据集中每个点的最近点?
【发布时间】: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 点的索引。

标签: python numpy loops


【解决方案1】:

我认为发生的事情是k=2 in

    distance, index = tree.query(data[['x', 'y','z']], k=2)

告诉KDTree 你想要最接近一点的两个点。所以最接近的显然是点本身,与自身的距离为零。此外,如果您打印index,您会看到一个 Nx2 数组,并且每一行都以行号开头。这是KDTree 的说法,离第 i 个点最近的点就是第 i 个点本身。

显然这没有用,您可能只需要第二个最近点。幸运的是,我在queryk 参数的文档中找到了这一点

返回的最近邻居的数量,或列表 要返回的第 k 个最近邻,从 1 开始。 https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.query.html#scipy.spatial.KDTree.query

所以

    distance, index = tree.query(data[['x', 'y','z']], k=[2])

只给出第二个到最近点的距离和索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多