检测后续整数序列的间隔

我有两个整数的向量。 我想确定在由第一个向量调节的第二个向量中呈现的连续整数序列的间隔(这个向量可以看作是一个因子,通过这个因子第二个向量可以被分成几个组)。

在这里,我提出了一个虚拟的问题。

数据在第二个向量的一个组(由第一个向量定义)中,整数单调递增。

my.data <- data.frame( V1=c(rep(1, 10), rep(2, 9), rep(3,11)), V2=c(seq(2,5), seq(7,11), 13, seq(4, 9), seq(11,13), seq(1, 6), seq(101, 105)) ) 

我想要的是:

  • 输出间隔的开始和结束
  • 这里,组在第一列,第二个开始整数,第三个结束整数。

预期成绩:

 1, 2, 5 \n 1, 7, 11 \n 1, 13, 13 \n 2, 4, 9 \n 2, 11, 13 \n 3, 1, 6 \n 3, 101, 105 \n 

这里是一个简短的答案使用聚合….

 runs <- cumsum( c(0, diff(my.data$V2) > 1) ) aggregate(V2 ~ runs + V1, my.data, range)[,-1] V1 V2.1 V2.2 1 1 2 5 2 1 7 11 3 1 13 13 4 2 4 9 5 2 11 13 6 3 1 6 7 3 101 105 

后来,我写了一个名为seqle()变体,因为它允许查找整数序列而不是重复。 那么,你可以做:

 Rgames: seqle(my.data[my.data$V1==1,2]) #repeat for my.data$V1 equal to 2 and 3 $lengths [1] 4 5 1 $values [1] 2 7 13 

(例如)。 将这些结果转换成你想要的表格forms需要一些小小的调整,但是我想我会提到它。 顺便说一下,这是seqle的代码。 如果你设置incr=0你会得到最基本的结果。

 function(x,incr=1){ if(!is.numeric(x)) x <- as.numeric(x) n <- length(x) y <- x[-1L] != x[-n] + incr i <- c(which(y|is.na(y)),n) list( lengths = diff(c(0L,i)), values = x[head(c(0L,i)+1L,-1L)]) } 

编辑:这是一个很好的升级,由flodel提供, 如何检查一个向量是否包含n个连续的数字 。 他指出,这个版本在使用双打时有通常的浮点错误问题,并提供了一个解决scheme。

这里是一个例子:

 library(plyr) ddply(my.data, .(V1), function(x) data.frame(do.call("rbind", tapply(x$V2, cumsum(c(T, diff(x$V2)!=1)), function(y) c(min(y), max(y)))))) 

也许太复杂了,但重要的是cumsum(c(T, diff(x$V2)!=1))

 > ddply(my.data, .(V1), + function(x) data.frame(do.call("rbind", tapply(x$V2, cumsum(c(T, diff(x$V2)!=1)), + function(y) c(min(y), max(y)))))) V1 X1 X2 1 1 2 5 2 1 7 11 3 1 13 13 4 2 4 9 5 2 11 13 6 3 1 6 7 3 101 105 

以下是使用plyr软件包中的plyr的解决scheme。 基本的想法是看diff(x)不是1的时候,为了find转换点。

 ddply( my.data, .(V1), summarise, lower = { cut_points <- which(diff(V2) != 1) V2[c(1, cut_points + 1)] }, upper = { cut_points <- which(diff(V2) != 1) V2[c(cut_points, length(V2))] } ) 
 my.data$run <- ave(my.data$V2, my.data$V1, FUN=function(x) c(1, diff(x))) strstp <- by(my.data, list(my.data$V1), FUN=function(x) list( starts=c( head(x$V2,1), x$V2[x$run != 1]), stops=c(x$V2[which(x$run != 1)-1], tail(x$V2, 1)))) > strstp : 1 $starts [1] 2 7 13 $stops [1] 5 11 13 ------------------------------------------------------------- : 2 $starts [1] 4 11 $stops [1] 9 13 ------------------------------------------------------------- : 3 $starts [1] 1 101 $stops [1] 6 105