如何获取滑动 windows 的组 ID 但仅在最早开始 window 完成后

How to get group id of sliding windows but only after completion of earliest started window

直说吧,我解释起来可能有点复杂。

让我们假设我有一个 运行 长度的向量(向前)滑动 window 大小。

xx <- c(3L, 2L, 1L, 4L, 4L, 3L, 3L, 1L, 2L, 1L, 2L, 3L, 4L, 3L, 2L, 1L)
xx
[1] 3 2 1 4 4 3 3 1 2 1 2 3 4 3 2 1

我想要的输出如下:

c(1, 1, 1, 2, 2, 2, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6)

带有丑陋 while 循环的选项:

xx <- c(3L, 2L, 1L, 4L, 4L, 3L, 3L, 1L, 2L, 1L, 2L, 3L, 4L, 3L, 2L, 1L)
#Initialise output vector
yy <- integer(length(xx))
#Assign the 1st group
yy[1:xx[1]] <- 1
#Set the current position
i <- xx[1] + 1
#Initialise the group number
group <- 2

#While all the groups have been assigned
while(any(yy == 0)) {
  #Assign the next group number
  yy[i:(i+xx[i] - 1)] <- group
  #Increment the group number
  group <- group + 1
  #Increment the current position.
  i <- i+xx[i]
}
yy

#[1] 1 1 1 2 2 2 2 3 4 4 5 5 6 6 6 6

这是使用 Rcpp 的可能方法:

Rcpp::cppFunction("
IntegerVector decode_rle(IntegerVector x) {
    const int n = x.size();
    IntegerVector res(n);
    int cnt = 0;
    int rle = x[0];
    int gcnt = 1;
    for(int i = 0; i < n; i ++){
        cnt++;
        if(cnt <= rle){
            res[i] = gcnt;
        }else{
            rle = x[i];
            cnt = 1;
            res[i] = ++gcnt;
        }
    }
    return res;
}")

xx <- c(3, 2, 1, 4, 4, 3, 3, 1, 2, 1, 2, 3, 4, 3, 2, 1)
decode_rle(xx)
# [1] 1 1 1 2 2 2 2 3 4 4 5 5 6 6 6 6

您可以使用 Reduce 和 return 您从中跳转到的 累积 索引。 as.factoras.integer 用于获取数字 1, 2, 3, ...

as.integer(as.factor(Reduce(function(i, j) if(i > j) i else i + xx[i+1],
 seq_len(length(xx)-1), xx[1], accumulate = TRUE)))
# [1] 1 1 1 2 2 2 2 3 4 4 5 5 6 6 6 6

另一种选择是使用递归函数。

f <- function(i) {
  if(i >= length(xx)) length(xx)
  else c(i, f(i + xx[i + 1]))
}

x <- diff(f(0))
rep(seq(x), x)
# [1] 1 1 1 2 2 2 2 3 4 4 5 5 6 6 6 6

从@GKi 的精彩 中获取线索,我将其翻译为 purrr::accumulate

accumulate(seq_len(length(xx)-1), .init = xx[1], ~ifelse(.x > .y, .x, .x + xx[.x +1]))

[1]  3  3  3  7  7  7  7  8 10 10 12 12 16 16 16 16

虽然不是您一开始想要的,但我终于找到了一种通过 recursion 获得所需输出的方法,这是我最喜欢的编程技术之一。我也试图在我的方法中尽可能简洁。希望你喜欢:

xx <- c(3L, 2L, 1L, 4L, 4L, 3L, 3L, 1L, 2L, 1L, 2L, 3L, 4L, 3L, 2L, 1L)

i <- 1
out <- c()
fn <- function(x) {
  out <<- c(out, rep(i, x[1]))
  x <- x[-(1:x[1])]
  if(length(x) != 0) {
    i <<- i + 1
  } else {
    return(out)
  }
  fn(x)
}

fn(xx)
[1] 1 1 1 2 2 2 2 3 4 4 5 5 6 6 6 6