为了账号安全,请及时绑定邮箱和手机立即绑定

在特定值的连续运行中创建计数器

在特定值的连续运行中创建计数器

慕斯王 2019-08-13 15:15:37
在特定值的连续运行中创建计数器我有小时价值。我想计算自上一次非零以来该值连续多少小时。对于电子表格或循环来说,这是一项简单的工作,但我希望有一个快速的矢量化单行程来完成任务。x <- c(1, 0, 1, 0, 0, 0, 1, 1, 0, 0)df <- data.frame(x, zcount = NA)df$zcount[1] <- ifelse(df$x[1] == 0, 1, 0)for(i in 2:nrow(df))   df$zcount[i] <- ifelse(df$x[i] == 0, df$zcount[i - 1] + 1, 0)期望的输出:R> df   x zcount1  1      02  0      13  1      04  0      15  0      26  0      37  1      08  1      09  0      110 0      2
查看完整描述

3 回答

?
森栏

TA贡献1810条经验 获得超5个赞

这里有一个方法,建立在约书亚的rle方法:(编辑以使用seq_len和lapply按马立克的建议)


> (!x) * unlist(lapply(rle(x)$lengths, seq_len))

 [1] 0 1 0 1 2 3 0 0 1 2

更新。只是为了踢,这是另一种方法,大约快5倍:


cumul_zeros <- function(x)  {

  x <- !x

  rl <- rle(x)

  len <- rl$lengths

  v <- rl$values

  cumLen <- cumsum(len)

  z <- x

  # replace the 0 at the end of each zero-block in z by the 

  # negative of the length of the preceding 1-block....

  iDrops <- c(0, diff(v)) < 0

  z[ cumLen[ iDrops ] ] <- -len[ c(iDrops[-1],FALSE) ]

  # ... to ensure that the cumsum below does the right thing.

  # We zap the cumsum with x so only the cumsums for the 1-blocks survive:

  x*cumsum(z)

}

试试一个例子:


> cumul_zeros(c(1,1,1,0,0,0,0,0,1,1,1,0,0,1,1))

 [1] 0 0 0 1 2 3 4 5 0 0 0 1 2 0 0

现在比较百万长度向量的时间:


> x <- sample(0:1, 1000000,T)

> system.time( z <- cumul_zeros(x))

   user  system elapsed 

   0.15    0.00    0.14 

> system.time( z <- (!x) * unlist( lapply( rle(x)$lengths, seq_len)))

   user  system elapsed 

   0.75    0.00    0.75 

故事的道德:单行更好,更容易理解,但并不总是最快!


查看完整回答
反对 回复 2019-08-13
?
千万里不及你

TA贡献1784条经验 获得超9个赞

William Dunlap关于R-help的帖子是寻找与跑步长度相关的所有事情的地方。他在这篇文章中的f7 是

f7 <- function(x){ tmp<-cumsum(x);tmp-cummax((!x)*tmp)}

在目前的情况下f7(!x)。在性能方面有

> x <- sample(0:1, 1000000, TRUE)> system.time(res7 <- f7(!x))
   user  system elapsed 
  0.076   0.000   0.077 > system.time(res0 <- cumul_zeros(x))
   user  system elapsed 
  0.345   0.003   0.349 > identical(res7, res0)[1] TRUE


查看完整回答
反对 回复 2019-08-13
?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

rle 将“计算自上一次非零以来该值连续多少小时”,但不是“所需输出”的格式。


请注意相应值为零的元素的长度:


rle(x)

# Run Length Encoding

#   lengths: int [1:6] 1 1 1 3 2 2

#   values : num [1:6] 1 0 1 0 1 0


查看完整回答
反对 回复 2019-08-13
  • 3 回答
  • 0 关注
  • 515 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信