类似于rle的函数捕获相邻整数的"运行"

aL3*_*3xa 8 r

我很确定你们都同意这rle是R中那些"陷阱"函数之一.是否有任何类似的函数可以"捕获"相邻整数值的"运行"?

所以,如果我有一个像这样的矢量:

x <- c(3:5, 10:15, 17, 22, 23, 35:40)
Run Code Online (Sandbox Code Playgroud)

我称之为深奥的功能,我会得到这样的响应:

lengths: 3, 6, 1, 2, 6
values: (3,4,5), (10,11,12... # you get the point
Run Code Online (Sandbox Code Playgroud)

编写这样的函数并不难,但仍然......任何想法?

G. *_*eck 8

1)根据值计算值然后计算长度

s <- split(x, cumsum(c(0, diff(x) != 1)))
run.info <- list(lengths = unname(sapply(s, length)), values = unname(s))
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

2)根据长度计算长度,然后计算值

这是基于Gregor长度计算的第二种解决方案:

lens <- rle(x - seq_along(x))$lengths 
list(lengths = lens, values = unname(split(x, rep(seq_along(lens), lens))))
Run Code Online (Sandbox Code Playgroud)

3)计算长度和值而不使用其他

这个似乎效率低下,因为它计算每个lengthsvalues从头开始,它似乎有点过于复杂但它确实设法将它全部归结为一个语句,所以我想我也会添加它.它基本上只是上面标记为1)和2)的前两个解决方案的混合.没有什么比这两个更新的了.

list(lengths = rle(x - seq_along(x))$lengths,
           values = unname(split(x, cumsum(c(0, diff(x) != 1)))))
Run Code Online (Sandbox Code Playgroud)

编辑:添加第二个解决方案.

编辑:添加第三个解决方案.  


Gre*_*gor 6

怎么样

rle(x - 1:length(x))$lengths   
# 3 6 1 2 6
Run Code Online (Sandbox Code Playgroud)

长度是你想要的长度,虽然我正在以一种同样聪明的方式消隐以获得正确的值,但是cumsum()原始x它们是非常容易接近的.


Hen*_*nry 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")
}
Run Code Online (Sandbox Code Playgroud)

并使用你的例子

> 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"
Run Code Online (Sandbox Code Playgroud)

这是约翰所期望的.

您可以进一步调整代码,以给出每个连续子序列的第一个而不是最后一个.