我很确定你们都同意rle
是R中的那些“陷阱”函数之一。是否有任何类似的函数可以“捕获”相邻整数值的“运行”?
所以,如果我有一个这样的矢量:
x <- c(3:5, 10:15, 17, 22, 23, 35:40)
我称之为深奥的功能,我会得到这样的响应:
lengths: 3, 6, 1, 2, 6
values: (3,4,5), (10,11,12... # you get the point
编写这样的函数并不难,但仍然......任何想法?
答案 0 :(得分:8)
1)根据值计算值然后计算长度
s <- split(x, cumsum(c(0, diff(x) != 1)))
run.info <- list(lengths = unname(sapply(s, length)), values = unname(s))
使用问题中的x
运行它会显示:
> str(run.info)
List of 2
$ lengths: int [1:5] 3 6 1 2 6
$ values :List of 5
..$ : num [1:3] 3 4 5
..$ : num [1:6] 10 11 12 13 14 15
..$ : num 17
..$ : num [1:2] 22 23
..$ : num [1:6] 35 36 37 38 39 40
2)根据长度计算长度,然后计算值
以下是基于Gregor's length calculation的第二种解决方案:
lens <- rle(x - seq_along(x))$lengths
list(lengths = lens, values = unname(split(x, rep(seq_along(lens), lens))))
3)在不使用其他
的情况下计算长度和值这个似乎效率低下,因为它从头开始计算lengths
和values
中的每一个并且它看起来有点过于复杂但它确实设法将它全部归结为单个语句所以我想我会添加它。它基本上只是上面标记为1)和2)的前两个解决方案的混合。没有什么比这两个更新的了。
list(lengths = rle(x - seq_along(x))$lengths,
values = unname(split(x, cumsum(c(0, diff(x) != 1)))))
编辑:添加了第二个解决方案。
编辑:添加了第三个解决方案。
答案 1 :(得分:6)
怎么样
rle(x - 1:length(x))$lengths
# 3 6 1 2 6
长度是你想要的长度,虽然我用一种同样聪明的方式来获得正确的值,但是cumsum()
和原始的x
它们非常容易接近。
答案 2 :(得分:5)
正如你所说,写一些类似rle
的东西很容易。实际上,通过添加rle
来调整+ 1
的代码可能会提供类似
rle_consec <- function(x)
{
if (!is.vector(x) && !is.list(x))
stop("'x' must be an atomic vector")
n <- length(x)
if (n == 0L)
return(structure(list(lengths = integer(), values = x),
class = "rle_consec"))
y <- x[-1L] != x[-n] + 1
i <- c(which(y | is.na(y)), n)
structure(list(lengths = diff(c(0L, i)), values = x[i]),
class = "rle_consec")
}
并使用您的示例
> x <- c(3:5, 10:15, 17, 22, 23, 35:40)
> rle_consec(x)
$lengths
[1] 3 6 1 2 6
$values
[1] 5 15 17 23 40
attr(,"class")
[1] "rle_consec"
这是约翰所期待的。
您可以进一步调整代码,以给出每个连续子序列的第一个而不是最后一个。
答案 3 :(得分:2)
我最近在此处发布了我的seqle
代码,基于此处发布的代码,甚至是:-)。