【问题标题】:Closest pair for any of a huge number of points大量点中任意点的最近对
【发布时间】:2013-05-16 01:22:48
【问题描述】:

我们在 2D 平面上得到了大量的点。我们需要为每个点找到集合中最近的点。例如假设初始集合如下:

 foo <- data.frame(x=c(1,2,4,4,10),y=c(1,2,4,4,10))

输出应该是这样的:

 ClosesPair(foo)
 2
 1
 4
 3
 3 # (could be 4 also)

有什么想法吗?

【问题讨论】:

标签: r points euclidean-distance


【解决方案1】:

传统的方法是对数据进行预处理 并将其放入数据结构中,通常是K-d tree, “最近点”查询速度非常快。

nnclust 包中有一个实现。

library(nnclust)
foo <- cbind(x=c(1,2,4,4,10),y=c(1,2,4,4,10))
i <- nnfind(foo)$neighbour
plot(foo)
arrows( foo[,1], foo[,2], foo[i,1], foo[i,2] )

【讨论】:

  • nnclust 在 cran 库中不再可用。存档中的最后一个可用版本是 2010 年。
【解决方案2】:

这是一个例子;全部包装成一个函数。您可能需要将其拆分一下以进行优化。

ClosesPair <- function(foo) {
  dist <- function(i, j) {
    sqrt((foo[i,1]-foo[j,1])**2 + (foo[i,2]-foo[j,2])**2)
  }

  foo <- as.matrix(foo)

  ClosestPoint <- function(i) {  
    indices <- 1:nrow(foo)
    indices <- indices[-i]

    distances <- sapply(indices, dist, i=i, USE.NAMES=TRUE)

    closest <- indices[which.min(distances)]
  }

  sapply(1:nrow(foo), ClosestPoint)
}
ClosesPair(foo)
# [1] 2 1 4 3 3

当然,它不能很好地处理关系。

【讨论】:

  • 谢谢,但它是否适用于大量积分,例如 1M 积分?
  • 是的,但有效吗?不确定。对于需要重新计算所有距离的每个点,它将在 O(n^2) 中运行,因此,如果您想要最佳解决方案,则无法解决此问题。空间方面,这通常是更紧迫的问题,它只使用 O(n)。如果您需要加快速度,您可以研究并行处理,这个函数可以很容易地重写为,或者启发式搜索算法,这在很大程度上取决于您的数据。
  • 您没有利用您的dist 函数已经矢量化的事实...将sapply(indices, dist, i=i, USE.NAMES=TRUE) 替换为dist(i, indices),您将看到巨大的改进。您还可以通过更有效地使用索引来使事情变得更快,例如,indices &lt;- 1:nrow(foo) 不应在循环内计算。并将sapply 替换为vapply。
【解决方案3】:

使用包 spatstat 。它有内置函数来做这类事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    相关资源
    最近更新 更多