在R中求公差范围内的值的指数

  • 本文关键字:范围内 指数
  • 更新时间 :
  • 英文 :


假设我有向量x

x <- c(1, 1, 1.1, 2, 1, 2.1, 2.6)
tol <- 0.4

我如何获得在公差范围(tol)内"唯一"的元素组的索引,如下面的列表所示。我不知道事先有多少这样的小组。

[[1]]
[1] 1 2 3 5
[[2]]
[1] 4 6
[[3]]
[1] 7

谢谢

不是100%可靠,因为它在list s上使用unique,但您可以尝试:

unique(apply(outer(x,x,function(a,b) abs(a-b)<tol),1,which))
#[[1]]
#[1] 1 2 3 5
#
#[[2]]
#[1] 4 6
#
#[[3]]
#[1] 7

@Roland在评论中提出的观点表明你们的要求有些模棱两可。例如,如果x<-c(1, 1.3, 1.6),我的线路给出了三个组:1-2、2-3和1-2-3。这是因为,从1的角度来看,它只与1.3相似,但从1.3的角度来看,它与11.6都相似。

使用RANN中的nn2查找半径内最近邻的替代方法:

library(RANN)
x <- c(1, 1, 1.1, 2, 1, 2.1, 2.6)
tol=0.4
nn <- nn2(x,x,k=length(x),searchtype="radius",radius=tol)
m <- unique(apply(nn$nn.idx,1,sort), MARGIN=2)
sapply(seq_len(ncol(m)), function(i) m[which(m[,i] > 0),i])
##[[1]]
##[1] 1 2 3 5
##
##[[2]]
##[1] 4 6
##
##[[3]]
##[1] 7
x <- c(1, 1.3, 1.6)
nn <- nn2(x,x,k=length(x),searchtype="radius",radius=tol)
m <- unique(apply(nn$nn.idx,1,sort), MARGIN=2)  
sapply(seq_len(ncol(m)), function(i) m[which(m[,i] > 0),i])
##[[1]]
##[1] 1 2
##
##[[2]]
##[1] 1 2 3
##
##[[3]]
##[1] 2 3

指出:

  1. 调用nn2在等于tol的半径范围内,查找x的每个元素相对于x的所有元素的所有最近邻居。结果nn$nn.idx是一个矩阵,其行包含x中每个元素的最近邻索引。矩阵是密集的,并根据需要填充零。
  2. 集群是通过对每一行进行排序来执行的,以便可以提取唯一的行。输出m是一个矩阵,其中每列包含集群中的索引。同样,这个矩阵是密集的,并根据需要填充0。
  3. 通过对每一列进行子设置以删除零条目来提取结果列表。

对于大型x来说,这可能更有效,因为nn2使用KD-Tree,但正如nicola指出的那样,对于重叠的元素(相对于容差),它也会遇到同样的问题。

也许这是一个杀死蚊子的锤子,但我想到了单变量密度聚类:dbscan库使您能够做到这一点:

library(dbscan)
groups <- dbscan(as.matrix(x), eps=tol, minPts=1)$cluster
#### [1] 1 1 1 2 1 2 3

你不需要事先知道组的数目。

它在输出中给你集群编号,但如果你愿意,你可以取组的平均值并将其四舍五入到最接近的整数。一旦得到了这些,就可以生成如下所示的列表:

    split(seq_along(x), groups)
#### $`1`
#### [1] 1 2 3 5
#### ...

编辑:重叠行为:该算法将同一组属性赋予在彼此容忍度范围内的所有元素(按接近度工作)。所以如果有重叠,你可能会得到比预期更少的组。

下面是对base r中的cut函数的另一个尝试。我们首先尝试创建名为sq的范围向量,然后遍历属于任何特定范围的x元素。

sq <- seq(min(x)-tol,max(x)+tol*2,tol*2)
# [1] 0.6 1.4 2.2 3.0
sapply(1:(length(sq)-1), function(i) which(!is.na(cut(x, breaks =c(sq[i], sq[i+1])))))
# [[1]]
# [1] 1 2 3 5
# [[2]]
# [1] 4 6
# [[3]]
# [1] 7

它不产生任何副本。(不需要使用unique,因为@nicola的答案就是这样)

它的工作原理如下,在sapply中,我们首先搜索[0.6, 1.4]范围内的元素,然后搜索[1.4, 2.2],最后搜索[2.2, 3.0]

最新更新