在一个向量中查找另一个向量中的值之间的值

时间:2014-11-06 07:07:49

标签: r

我需要一些帮助来查找矢量中介于键值之间的值,不包括在内。

例如,使用以下向量xy

x <- c(2, 6, 10)
y <- c(7, 1, 9, 12, 4, 6, 3)

我想在y中找到x但不等于x的所有值,以便结果为

list(y[y > 2 & y < 6], y[y > 6 & y < 10])
# [[1]]
# [1] 4 3
#
# [[2]]
# [1] 7 9

所以在上面的结果中,

  • 3和4在2和6之间
  • 7和9介于6和10之间
  • 12不介于任何内容之间,因此不包括在内
  • 6等于6,所以它也被排除在外

我现在已经做了一段时间了,我很难过。我会告诉你代码,但它很简单。

如何在一个向量中快速找到另一个向量中值之间的值?

4 个答案:

答案 0 :(得分:7)

也许这对你有用:

lapply(split(y[y > min(x) & y < max(x)], 
             findInterval(y[y > min(x) & y < max(x)], x)), 
       function(z) z[!z %in% x]) 
# $`1`
# [1] 4 3
# 
# $`2`
# [1] 7 9

当然,保持DRY和子集&#34; y&#34;可能会更好。在拆分之前,例如,使用来自&#34; data.table&#34;的between(或%between%}:

library(data.table)
Z <- y[y %between% range(x) & !y %in% x]
split(Z, findInterval(Z, x))
# $`1`
# [1] 4 3
#
# $`2`
# [1] 7 9

更新

作为参考,目前为止所有三个选项都非常快:

set.seed(1)
x <- sort(sample(100000, 20, FALSE))
y <- sample(100000, 100000, TRUE)

AM <- function(x, y) {
  Z <- y[y %between% range(x) & !y %in% x]
  split(Z, findInterval(Z, x))
}

DA <- function(x, y) {
  indx <- Map(function(x, z) x + seq_len(z), x[-length(x)], diff(x) - 1)
  lapply(indx, function(x) y[y %in% x])
}

user <- function(x, y) {
  m <- t(diff(sign(outer(x, y, "-"))) == 2)
  split((m*y)[m], col(m)[m])
}

library(microbenchmark)
microbenchmark(AM(x, y), DA(x, y), user(x, y))
# Unit: milliseconds
#        expr       min        lq      mean    median        uq      max neval
#    AM(x, y)  22.58939  23.24731  26.29092  23.79639  25.64548 140.5610   100
#    DA(x, y) 149.46997 157.48534 162.47526 160.01823 164.74851 287.0808   100
#  user(x, y) 327.38835 437.44064 445.71955 446.65938 467.97784 637.3121   100

答案 1 :(得分:5)

这是另一种方法

indx <- Map(function(x, z) x + seq_len(z), x[-length(x)], diff(x) - 1)
lapply(indx, function(x) y[y %in% x])
# [[1]]
# [1] 4 3
# 
# [[2]]
# [1] 7 9 

答案 2 :(得分:4)

另一种变化。我想你可以使用outersign;如果从1更改为-1,则遍历列,y值在x范围内(即连续列总和为零)。提取值的循环虽然有点混乱。

修改 @flodel在评论中提供了一个不错的选择

m <- t(diff(sign(outer(x, y, "-"))) == 2)
split((m*y)[m], col(m)[m])


原始

(o <- sign(outer(y, x, "-")))
#       [,1] [,2] [,3]
# [1,]    1    1   -1
# [2,]   -1   -1   -1
# [3,]    1    1   -1
# [4,]    1    1    1
# [5,]    1   -1   -1
# [6,]    1    0   -1
# [7,]    1   -1   -1

lapply(1:(length(x)-1), function(i) y[o[,i] + o[,i+1]==0])
# [[1]]
# [1] 4 3
# 
# [[2]]
# [1] 7 9

答案 3 :(得分:0)

Try:

z =list()
for(j in 1:(length(x)-1)) {
    v=NULL
    for(i in 1:length(y))   
       if(y[i]>x[j] && y[i]<x[j+1]) 
            v[length(v)+1]=y[i]
    z[[length(z)+1]] = v
}
z
[[1]]
[1] 4 3

[[2]]
[1] 7 9