检查向量的元素是否在矩阵给定的区间内
Check whether elements of vectors are inside intervals given by matrix
我想出了一个解决方案(见下文),这实际上是一个非常好的问题,但是并不漂亮:
假设您有一个 向量 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
有办法) .
我们可以用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
这是一个不使用显式循环或应用函数的方法。 outer
有时要快得多。
x[rowSums(outer(x, A[,1], `>=`) & outer(x, A[,2], `<=`)) > 0]
[1] 4 15
这个回答晚了,但今天我有同样的问题要解决,我的回答可能对未来的读者有所帮助。我的解决方案如下:
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)))
}
这个函数return一个长度为(x)的逻辑向量,指示是否可以在区间中找到x中的对应值。如果我想得到我只需要写的元素
x[f3(x,A)]
我做了一些基准测试,我的函数似乎工作得很好,在用更大的数据进行测试时也是如此。
让我们在此 post:
中定义此处建议的其他解决方案
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
}
现在他们也在 returning 一个逻辑向量。
我机器上的基准测试如下:
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
可以检查所有函数 return 相同的结果,例如通过:
all(f1(x,A)==f3(x,A))
我想出了一个解决方案(见下文),这实际上是一个非常好的问题,但是并不漂亮:
假设您有一个 向量 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
有办法) .
我们可以用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
这是一个不使用显式循环或应用函数的方法。 outer
有时要快得多。
x[rowSums(outer(x, A[,1], `>=`) & outer(x, A[,2], `<=`)) > 0]
[1] 4 15
这个回答晚了,但今天我有同样的问题要解决,我的回答可能对未来的读者有所帮助。我的解决方案如下:
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)))
}
这个函数return一个长度为(x)的逻辑向量,指示是否可以在区间中找到x中的对应值。如果我想得到我只需要写的元素
x[f3(x,A)]
我做了一些基准测试,我的函数似乎工作得很好,在用更大的数据进行测试时也是如此。 让我们在此 post:
中定义此处建议的其他解决方案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
}
现在他们也在 returning 一个逻辑向量。 我机器上的基准测试如下:
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
可以检查所有函数 return 相同的结果,例如通过:
all(f1(x,A)==f3(x,A))