假设我有以下数据:
c(1:4,7:15,20:23,25,30:35,40,41)
我想要得到这个向量的起始和结束范围。然而,我想跳过单个值,它没有自然的前驱和后继(在示例中:25)。换句话说,至少要有两个连续的值才能构成一个"范围"。
本例中起始范围为:1, 7, 20, 30, 40
它们对应的结束范围为:4, 15, 23, 35, 41
是否有优雅的内置解决方案?我几乎被困在for循环的地狱里了。
确定diff(x)
所在位置>1,通过在序列的开头或结尾添加TRUE
来适当地滞后。(diff(x)
产生一个比x
短一个元素的向量。)&
子句去掉了单例值。
dx1 <- c(TRUE,diff(x)>1)
dx2 <- c(diff(x)>1, TRUE)
start <- x[dx1 & !dx2]
end <- x[dx2 & !dx1]
也可能有一个类似rle(diff(x)==1)
的解决方案,但它会比上面的解决方案更复杂一些(如果你想要识别特定长度的运行,它可能会有用)。
对@Ben Bolker的解决方案没有多大帮助,但另一种方法可以是:
ind <- aggregate(x ~ cumsum(c(FALSE, diff(x)) > 1), FUN = function(x) (length(x) > 1) * range(x))
ind$x[ind$x[, 1] != 0, ]
[,1] [,2]
[1,] 1 4
[2,] 7 15
[3,] 20 23
[4,] 30 35
[5,] 40 41