R:检查向量的元素是否在矩阵给出的区间内

时间:2018-06-09 13:21:38

标签: r performance loops apply intervals

实际上我提出了一个非常好的问题,我提出了一个解决方案(见下文),但这并不美观:

假设你有一个向量x 和一个矩阵A ,它包含第一列中间隔的开始和第二列中间隔的结束。 /> 如何获得A 的元素,这些元素属于A 给出的区间?

x <- c(4, 7, 15)

A <- cbind(c(3, 9, 14), c(5, 11, 16))

预期产出:

[1] 4 15

如果这有助于提高绩效,您可以获得以下信息:
矩阵的向量和行都是有序的,间隔不重叠。所有间隔都具有相同的长度。所有数字都是整数,但可以巨大

现在我不想懒惰并提出以下解决方案,这对于长矢量和矩阵来说太慢了:

x <- c(4, 7, 15)  # Define input vector

A <- cbind(c(3, 9, 14), c(5, 11, 16))  # Define matrix with intervals

b <- vector()

for (i in 1:nrow(A)) {
  b <- c(b, A[i, 1]:A[i, 2])
}

x[x %in% b]

我知道 R 中的循环可能很慢,但我不知道如何在没有一个的情况下编写操作(也许有apply的方法。)

3 个答案:

答案 0 :(得分:1)

我们可以使用sapply循环遍历x的每个元素,并查找它是否位于这些矩阵值的any范围内。

x[sapply(x, function(i) any(i > A[, 1] & i < A[,2]))]
#[1]  4 15

如果length(x)nrow(A)相同,那么我们甚至不需要sapply循环,我们可以直接使用此比较。

x[x > A[, 1] & x < A[,2]]
#[1]  4 15

答案 1 :(得分:1)

这是一种不使用显式循环或应用函数的方法。 outer有时要快得多。

x[rowSums(outer(x, A[,1], `>=`) & outer(x, A[,2], `<=`)) > 0]

[1]  4 15

答案 2 :(得分:0)

这个答案很晚,但是今天我有同样的问题要解决,我的答案可能对将来的读者有所帮助。我的解决方案如下:

f3 <- function(x,A) {
  Reduce(f = "|",
         x = lapply(1:NROW(A),function(k) x>A[k,1] & x<A[k,2]), 
         init = logical(length(x)))
}

此函数返回一个长度为(x)的逻辑向量,指示是否可以在间隔中找到x中的相应值。如果我想获取元素,我只需要写

x[f3(x,A)]

我做了一些基准测试,并且在使用较大数据进行测试时,我的功能似乎运行良好。 让我们定义本文中建议的其他解决方案:

f1 <- function(x,A) {
  sapply(x, function(i) any(i > A[, 1] & i < A[,2]))
}

f2 <- function(x,A) {
  rowSums(outer(x, A[,1], `>`) & outer(x, A[,2], `<`)) > 0
}

现在它们还返回逻辑向量。 我的计算机上的基准测试如下:

x <- c(4, 7, 15)
A <- cbind(c(3, 9, 14), c(5, 11, 16))
microbenchmark::microbenchmark(f1(x,A), f2(x,A), f3(x,A))

#Unit: microseconds
#     expr  min    lq   mean median    uq  max neval
#f1(x, A) 21.5 23.20 25.023  24.30 25.40 61.8   100
#f2(x, A) 18.8 21.20 23.606  22.75 23.70 75.4   100
#f3(x, A) 13.9 15.85 18.682  18.30 19.15 52.2   100

似乎没有什么大的区别,但是下面的示例将使它更加明显:

x <- seq(1,100,length.out = 1e6)
A <- cbind(20:70,(20:70)+0.5)
    
microbenchmark::microbenchmark(f1(x,A), f2(x,A), f3(x,A), times=10)

#Unit: milliseconds
#     expr      min        lq      mean    median        uq       max neval
#f1(x, A) 4176.172 4227.6709 4419.6010 4484.2946 4539.9668 4569.7412    10
#f2(x, A) 1418.498 1511.5647 1633.4659 1571.0249 1703.6651 1987.8895    10
#f3(x, A)  614.556  643.4138  704.3383  672.5385  770.7751  873.1291    10

可以检查所有函数返回相同结果的方法,例如通过:

all(f1(x,A)==f3(x,A))