【问题标题】:choose n most distant points in R在R中选择n个最远的点
【发布时间】:2014-03-03 16:52:06
【问题描述】:

给定一组 xy 坐标,我如何选择 n 个点,使这 n 个点彼此相距最远?

一种低效的方法可能不适用于大型数据集,如下所示(从 1000 个点中找出最远的 20 个点):

xy <- cbind(rnorm(1000),rnorm(1000))

n <- 20
bestavg <- 0
bestSet <- NA
for (i in 1:1000){
    subset <- xy[sample(1:nrow(xy),n),]
    avg <- mean(dist(subset))
    if (avg > bestavg) {
        bestavg <- avg
        bestSet <- subset
    }
}

【问题讨论】:

  • 假设你有 10 个点,你想找到 4 个点的子集,比如说,最大化 6 个点间距离之和的点?
  • 是的,我认为这会得到我正在寻找的结果......
  • 组合数学对你不利的是 1000 个点和 20 个子集。计算所有 1000x1000 距离如何,删除两个最近点,重新计算距离,重复 980 次。比迭代超过 10^50 个组合更快。
  • 我同意@Spacedman。但也许这是在Computer Science SO 上提出的更好的问题?一个有效的算法可能并不特定于 R,并且那里的用户可能已经知道最好的算法。
  • 您在每一步都重新计算距离矩阵。为什么?只需根据该步骤的剩余点对其进行子集化即可。

标签: r distance


【解决方案1】:

此代码基于 Pascal 的代码,删除距离矩阵中行和最大的点。

m2 <- function(xy, n){

    subset <- xy

    alldist <- as.matrix(dist(subset))

    while (nrow(subset) > n) {
        cdists = rowSums(alldist)
        closest <- which(cdists == min(cdists))[1]
        subset <- subset[-closest,]
        alldist <- alldist[-closest,-closest]
    }
    return(subset)
}

在高斯云上运行,其中m1 是@pascal 的函数:

> set.seed(310366)
> xy <- cbind(rnorm(1000),rnorm(1000))
> m1s = m1(xy,20)
> m2s = m2(xy,20)

通过查看点间距离的总和来了解谁做得最好:

> sum(dist(m1s))
[1] 646.0357
> sum(dist(m2s))
[1] 811.7975

方法 2 获胜!并与 20 个点的随机样本进行比较:

> sum(dist(xy[sample(1000,20),]))
[1] 349.3905

效果不如预期。

那么发生了什么?让我们绘制:

> plot(xy,asp=1)
> points(m2s,col="blue",pch=19)
> points(m1s,col="red",pch=19,cex=0.8)

方法 1 生成红点,这些红点在空间上均匀分布。方法 2 创建几乎定义周长的蓝点。我怀疑这样做的原因很容易解决(在一个维度上甚至更容易......)。

使用初始点的双峰模式也说明了这一点:

同样,方法 2 产生的总和距离比方法 1 大得多,但两者都比随机抽样好:

> sum(dist(m1s2))
[1] 958.3518
> sum(dist(m2s2))
[1] 1206.439
> sum(dist(xy2[sample(1000,20),]))
[1] 574.34

【讨论】:

  • 虽然方法 m1 的结果更符合我的要求,但从技术上讲,您的解决方案在回答问题方面做得更好。
  • 那么我认为您需要仔细考虑您要寻找的是什么,因为它不是具有最大总和点间距离的点集!可能是点 A 的集合最小化到 A 中的点 not 的距离总和吗?这可能会给您类似m1 的信息,因为它会尝试将选定点均匀分布在未选定对象中...
  • 是的,我想你刚才描述的正是我想要的。
  • 我认为您需要将其正式化并开始一个新问题!
【解决方案2】:

按照@Spacedman 的建议,我编写了一个函数,该函数从最近的对中删除一个点,直到保留所需的点数。它似乎运作良好,但是随着您的加分,它会很快变慢。

xy <- cbind(rnorm(1000),rnorm(1000))

n <- 20

subset <- xy

alldist <- as.matrix(dist(subset))
diag(alldist) <- NA
alldist[upper.tri(alldist)] <- NA

while (nrow(subset) > n) {
    closest <- which(alldist == min(alldist,na.rm=T),arr.ind=T)
    subset <- subset[-closest[1,1],]
    alldist <- alldist[-closest[1,1],-closest[1,1]]
}

【讨论】:

  • 更好的方法可能是删除具有最小行总和的点(在整个距离矩阵上)——这将对我们试图最小化的数量贡献最大的点......跨度>
猜你喜欢
  • 2013-10-07
  • 2017-04-22
  • 1970-01-01
  • 2015-03-17
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多