R 如何计算逻辑向量中的1序列

R 如何计算逻辑向量中的1序列,r,R,我有一个逻辑向量,比如 as.logical(c(0,0,1,1,1,0,1,1,0,0,0,1,1,1,1)) 但时间要长得多。如何将其转换为: c(0,0,1,2,3,0,1,2,0,0,0,1,2,3,4) 通过计算一的长度?您可以在数据表中使用rleid A=as.logical(c(0,0,1,1,1,0,1,1,0,0,0,1,1,1,1)) B=data.table::rleid(A) B=ave(B,B,FUN = seq_along) B[!A]=0 B [1] 0 0 1

我有一个逻辑向量,比如

as.logical(c(0,0,1,1,1,0,1,1,0,0,0,1,1,1,1))
但时间要长得多。如何将其转换为:

c(0,0,1,2,3,0,1,2,0,0,0,1,2,3,4)

通过计算一的长度?

您可以在
数据表中使用
rleid

A=as.logical(c(0,0,1,1,1,0,1,1,0,0,0,1,1,1,1))
B=data.table::rleid(A)
B=ave(B,B,FUN = seq_along)
B[!A]=0
B
[1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4

x这是一个使用基本R的
rle
Map

x <- as.logical(c(0,0,1,1,1,0,1,1,0,0,0,1,1,1,1))
unlist(Map(function(l, v) if (!isTRUE(v)) rep(0, l) else 1:l, rle(x)$lengths, rle(x)$values))
# [1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4

另一个
rle
选项:

r <- rle(x)
x[x] <- sequence(r$l[r$v])
#[1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4

C++与<<代码> Rcpp <代码> < /P>

library(Rcpp)

cppFunction('NumericVector seqOfLogical(LogicalVector lv) {
  size_t n = lv.size();
  NumericVector res(n);
  int foundCounter = 0;
  for (size_t i = 0; i < n; i++) {
    if (lv[i] == 1) {
      foundCounter++;
    } else {
      foundCounter = 0;
    }
    res[i] = foundCounter;
  }
  return res;
}')

seqOfLogical(x)

# [1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4
库(Rcpp)
cppFunction('数字向量序列逻辑(LogicalVector lv){
尺寸n=lv.size();
数值向量res(n);
int foundCounter=0;
对于(大小i=0;i

基准
库(微基准)
种子(1)

x与温的略有不同,我想到:

library(data.table)
ave(v,rleid(v),FUN=function(x) x *seq_along(x))
# [1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4
我建议使用计算连续事件的包和函数。也可能对滑动窗口进行计算(如最后5次观察),更多信息请参见


x为基准测试欢呼(+1)!我有点羞于在名单上垫底;一定是表现焦虑;-)@我喜欢这些类型的“循环”问题,因为它们展示了简单的C/C++知识是如何大幅提高代码速度的。
x[x] <- sequence(with(rle(x), lengths[values]))
library(Rcpp)

cppFunction('NumericVector seqOfLogical(LogicalVector lv) {
  size_t n = lv.size();
  NumericVector res(n);
  int foundCounter = 0;
  for (size_t i = 0; i < n; i++) {
    if (lv[i] == 1) {
      foundCounter++;
    } else {
      foundCounter = 0;
    }
    res[i] = foundCounter;
  }
  return res;
}')

seqOfLogical(x)

# [1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4
library(microbenchmark)

set.seed(1)
x <- sample(c(T,F), size = 1e6, replace = T)

microbenchmark(
    symbolix = { symbolix(x) }, 
    thelatemail1 = { thelatemail1(x) },
    thelatemail2 = { thelatemail2(x) },
    wen = { wen(x) },
    maurits = { maurits(x) },
    #mhammer = { mhammer(x) },   ## this errors
    times = 5
)

# Unit: milliseconds
#         expr         min          lq       mean      median         uq       max neval
#     symbolix    2.760152    4.579596   34.60909    4.833333   22.31126  138.5611     5
# thelatemail1  154.050925  189.784368  235.16431  235.982093  262.33704  333.6671     5
# thelatemail2  138.876834  146.197278  158.66718  148.547708  179.80223  179.9119     5
#          wen  780.432786  898.505231 1091.39099 1093.702177 1279.33318 1404.9816     5
#      maurits 1002.267323 1043.590621 1136.35624 1086.967756 1271.38803 1277.5675     5
symbolix <- function(x) {
    seqOfLogical(x)
}

thelatemail1 <- function(x) {
    r <- rle(x)
    x[x] <- sequence(r$l[r$v])
    return(x)
}

thelatemail2 <- function(x) {
    x[x] <- sequence(with(rle(x), lengths[values]))
    return(x)
}

maurits <- function(x) {
    unlist(Map(function(l, v) if (!isTRUE(v)) rep(0, l) else 1:l, rle(x)$lengths, rle(x)$values))
}

wen <- function(A) {
    B=data.table::rleid(A)
    B=ave(B,B,FUN = seq_along)
    B[!A]=0
    B
}

mhammer <- function(x) {
    x_counts <- x
    for(i in seq_along(x)) {
      if(x[i] == 1) { x_counts[i] <- x_counts[i] + x_counts[i-1] }
    }
    return(x_counts)
}
library(data.table)
ave(v,rleid(v),FUN=function(x) x *seq_along(x))
# [1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4
x <- as.logical(c(0,0,1,1,1,0,1,1,0,0,0,1,1,1,1))

streak <- streak_run(x)
streak[x == 0] <- 0

print(streak)
# [1] 0 0 1 2 3 0 1 2 0 0 0 1 2 3 4