假设我有这个整数vector:
> int.vec
[1] 1 2 3 5 6 7 10 11 12 13
Run Code Online (Sandbox Code Playgroud)
(来自int.vec <- c(1:3,5:7,10:13))
我正在寻找一个函数,它将返回此向量中所有区间长度的总和.
所以基本上int.vec这个函数会返回:
3+3+4 = 10
Run Code Online (Sandbox Code Playgroud)
A5C*_*2T1 12
"cgwtools"包有一个调用的函数seqle,在这里可能会有所帮助.
library(cgwtools)
int.vec <- c(1:3,5:7,10:13)
seqle(int.vec)
# Run Length Encoding
# lengths: int [1:3] 3 3 4
# values : int [1:3] 1 5 10
Run Code Online (Sandbox Code Playgroud)
结果是a list,因此您只需访问并总结"长度"值:
sum(seqle(int.vec)$lengths)
# [1] 10
Run Code Online (Sandbox Code Playgroud)
Sym*_*xAU 12
length(int.vec)
# 10
Run Code Online (Sandbox Code Playgroud)
您的间隔是数字序列,x1:xn,x1:xm,x1:xp,其中,每个向量的(或间隔在这种情况下)的长度n,m和p分别.
整个向量的长度为length(x1:xn)+ length(x1:xm)+ length(x1:xp),与...相同length(n + m + p).
现在,如果我们真的对每个单独的序列载体的长度感兴趣,我们就可以做到
int.vec <- c(1:3,5:7,10:13)
## use run-length-encoding (rle) to find sequences where the difference == 1
v <- rle(diff(int.vec) == 1)[[1]]
v[v!=1] + 1
# [1] 3 3 4
Run Code Online (Sandbox Code Playgroud)
并且,正如@AHandcartAndMohair所指出的,如果您正在使用列表,则可以使用 lengths
int.list <- list(c(1:3), c(5:7), c(10:13))
lengths(int.list)
# [1] 3 3 4
Run Code Online (Sandbox Code Playgroud)
我们可以通过取相邻元素的差值来创建分组变量,检查它是否不等于1,得到cumsum,使用tapply来获取length和sum输出。
sum(tapply(int.vec,cumsum(c(TRUE,diff(int.vec) !=1)), FUN=length))
#[1] 10
Run Code Online (Sandbox Code Playgroud)
或者使用table和sum
sum(table(int.vec,cumsum(c(TRUE,diff(int.vec) !=1))))
#[1] 10
Run Code Online (Sandbox Code Playgroud)
或者我们split使用源自cumsum(split非常快)的分组变量的“int.vec”并使用(另一个快速选项)获取length每个list元素lengths- 由@Frank贡献
sum(lengths(split(int.vec, cumsum(c(0,diff(int.vec)>1)))))
Run Code Online (Sandbox Code Playgroud)
注意:没有使用任何包。只需移除包装器,这将有助于识别length每个组件的个体(如果我们需要的话)sum。
根据 @Symbolix 解决方案的进一步见解,OP 的预期输出length只是vector.
NROW(int.vec)
#[1] 10
Run Code Online (Sandbox Code Playgroud)
也可以使用。如果我们正在使用data.frame. 但是,正如我上面提到的,OP 似乎需要识别length每个间隔的 以及length. 该解决方案同时提供了两者。