【问题标题】:Efficient method for counting number of data points inside sphere of fixed radius centered on each data point计算以每个数据点为中心的固定半径球内数据点数量的有效方法
【发布时间】:2019-05-25 15:06:31
【问题描述】:

我有一个数据库,其中包含许多数据点,每个数据点都有一个 x、y、z 坐标。我想计算到相邻点一定距离内的点数。有些点会有一对在半径 R 内,有些则不会。我只是想计算一段距离内的对数。我可以很容易地编写一个算法来做到这一点,但它的效率不够高(因为我会遍历每一个数据点)。

这似乎必须已经存在于 astropy、scipy 等中,但我似乎无法找到我正在寻找的东西。有什么东西可以做到这一点吗?

【问题讨论】:

  • 你有什么证据证明“它不够高效”?
  • 找到一个现有的实现是题外话,但你想要的是一个空间搜索数据结构,如 k-d 树、八叉树、或简单的单元格箱。
  • @martineau 是的。我实际上并没有实现它,我只是假设使用距离公式超过 200 万次需要很长时间,但也许这实际上是可行的......似乎应该有更好的方法。
  • Jake:2M 并不多(具体取决于您在做什么),并且有一些简单的方法可以加快距离计算,例如使用平方值。有时可能会很困难,但通常可以避免过早的优化。一位著名的计算机科学家(据说)曾经声称它是万恶之源。
  • 天文和天文标签在这里似乎并不相关。

标签: python astronomy astropy


【解决方案1】:

正如@Davis Herring 在 cmets 中提到的,一个有效的选择是 k-d 树。

k-d 树是一种避免蛮力方法并允许有效距离计算的算法*(背景见答案底部)。

这有几个 Python 实现,其中之一是通过SciPy

SciPy k-d tree in Cython(使用 C/Cython 更快)

SciPy k-d tree in pure Python

您可以通过首先为您的 xyz 数据构建一个 k-d 树来使用它:

import numpy as np  #for later code
from scipy.spatial import cKDTree

kdtree = cKDTree(xyzData)

然后,您必须使用点 point 查询 k-d 树,以计算 point 与其最近邻居之间的距离。此查询的输出是point 与其最近邻居之间的距离NN_dist 以及该邻居的索引NN_idx。要计算所有点的值,我们需要一个 for 循环,但考虑到 k-d 树算法,这比蛮力计算要快得多:

NN_dists = np.zeros(numPoints)  #pre-allocate an array to store distances
for i in range(numPoints):
    point = xyzData[i]

    NN_dist, NN_idx = kdtree.query(point,k=[1])

    #Note: 'k' specifies the kth neighbor distance to compute, 
    #so set k=2 if you end up finding the point as its own "neighbor":
    if NN_dist == 0:
        NN_dist, NN_idx = targetTree.query(curCoord,k=[2])
    
    NN_dists[i] = NN_dist

(详情请参阅k-d tree query)。

然后,要查找低于某个阈值的距离,您可以在使用比较运算符时使用 NumPy 数组的内置实用程序(如 <):

distanceThres = 10
goodIdx = NN_dists < distanceThres
goodPoints = xyzData[goodIdx]

这将为您提供位于指定距离阈值distanceThres 内的索引goodIdx 和点goodPoints(尽管您可能必须根据xyz 坐标数据的形状/格式更改此代码)。


*k-d 树上的浅色背景(对细节进行修饰——更多信息请参阅参考资料):k-d 树方法以避免计算每个点之间的距离的方式对数据集进行分区(即蛮力方法) )。它通过将数据集划分为二进制空间分区来构建 k-d 树来做到这一点。这些分区使得距离计算(例如,最近邻搜索)可以忽略远处分区中的数据点。此外,每个点都会重复使用相同的 k-d 树。

网上有很多关于 k-d 树的资源。当我学习这个算法时,我发现这些参考资料最有帮助:Stanford k-d treesPrinceton k-d trees

如果您有任何问题,请告诉我——我自己在一个天文学项目中遇到了这个确切的问题,所以我可以提供更多帮助。

【讨论】:

    【解决方案2】:

    我没有直接的经验,但scipy.spatial.distance.pdist 可能就是您要找的。​​p>

    这个link 也可能会有所帮助。它给出了一个如何解决我理解的问题的示例。

    【讨论】:

      猜你喜欢
      • 2023-04-06
      • 2017-04-13
      • 2016-09-21
      • 2016-09-21
      • 2018-11-02
      • 2020-09-23
      • 1970-01-01
      • 2014-07-30
      • 2016-07-21
      相关资源
      最近更新 更多