首先,我简化我的问题。我想从数值向量中提取某些范围。例如,同时从1:20
中提取3个范围:
因此,预期输出为2, 3, 4, 9, 10, 11, 18, 19
。
我尝试使用函数findInterval()
和控制参数rightmost.closed
和left.open
来做到这一点,但是任何参数集都无法实现目标。
x <- 1:20
v <- c(1, 5, 8, 12, 17, 20)
x[findInterval(x, v) %% 2 == 1]
# [1] 1 2 3 4 8 9 10 11 17 18 19
x[findInterval(x, v, rightmost.closed = T) %% 2 == 1]
# [1] 1 2 3 4 8 9 10 11 17 18 19 20
x[findInterval(x, v, left.open = T) %% 2 == 1]
# [1] 2 3 4 5 9 10 11 12 18 19 20
顺便说一句,条件也可以是这样的矩阵:
[,1] [,2]
[1,] 1 5
[2,] 8 12
[3,] 17 20
如果不需要,我不想使用for
循环。
我非常感谢您的帮助。
答案 0 :(得分:5)
我可能会使用purrr :: map2或Map进行操作,将您的下限和上限作为参数传递,并使用自定义函数过滤数据集
library(purrr)
x <- 1:20
lower_bounds <- c(1, 8, 17)
upper_bounds <- c(5, 12, 20)
map2(
lower_bounds, upper_bounds, function(lower, upper) {
x[x > lower & x < upper]
}
)
答案 1 :(得分:4)
您可以使用data.table::inrange
及其incbounds
参数。假设范围在矩阵“ m”中,如您的问题所示:
x[data.table::inrange(x, m[ , 1], m[ , 2], incbounds = FALSE)]
# [1] 2 3 4 9 10 11 18 19
m <- matrix(v, ncol = 2, byrow = TRUE)
答案 2 :(得分:2)
您在正确的道路上,left.open
确实有帮助,但是rightmost.closed
实际上仅涉及最后一个间隔,而不是每个间隔的右侧。因此,我们需要使用两次left.open
。如您自己所知,这似乎是一种最佳的方法
x[findInterval(x, v) %% 2 == 1 & findInterval(x, v, left.open = TRUE) %% 2 == 1]
# [1] 2 3 4 9 10 11 18 19
很显然,还有其他选择。例如,
fun <- function(x, v)
if(length(v) > 1) v[1] < x & x < v[2] | fun(x, v[-1:-2]) else FALSE
x[fun(x, v)]
# [1] 2 3 4 9 10 11 18 19
答案 3 :(得分:1)
仅使用sapply()
,我发现了一种简单的方法:
x <- 1:20
v <- c(1, 5, 8, 12, 17, 20)
(v.df <- as.data.frame(matrix(v, 3, 2, byrow = T)))
# V1 V2
# 1 1 5
# 2 8 12
# 3 17 20
y <- sapply(x, function(x){
ind <- (x > v.df$V1 & x < v.df$V2)
if(any(ind)) x else NA
})
y[!is.na(y)]
# [1] 2 3 4 9 10 11 18 19