Find indices of values ​​within an acceptable range in R

Say I have a vector x

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

how can I get indices of groups of elements that are "unique" within the tolerance range ( tol), as in the list below. I do not know how many of these groups are in advance.

[[1]]
[1] 1 2 3 5

[[2]]
[1] 4 6

[[3]]
[1] 7

thank

+4
source share
4 answers

Not 100% reliable, as it uses uniqueon lists, but you can try:

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 1, 1.6.

+2

, , , : 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
#### ...

: : , ( ). , , , .

+1

, nn2 RANN, :

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

:

  • nn2 x x , tol. nn$nn.idx - , , x. .
  • , . m - , . , .
  • .

, , x, nn2 KD-Tree, , ( ), nicola.

+1

Here is another attempt with a function cutfrom the R base. First, we will try to create a range vector with a name sq, and then go through elements xthat fall into any specific range.

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

It does not duplicate. (no need to use unique, as is the case for @nicola's answer)

It works as follows: sapplyfirst we look for elements in the range [0.6, 1.4], then for [1.4, 2.2]and finally [2.2, 3.0].

0
source

Source: https://habr.com/ru/post/1654550/


All Articles