I recommend runner package and function streak_run
which calculates consecutive occurences. Possible also calculating on sliding windows (eg. last 5 observations), more in github documentation
library(runner)
streak <- streak_run(x)
streak[x == 0] <- 0
print(streak)
# [1] 0 1 2 0 1 2 0 1 0 1
Compare speed with other solutions
fun_ave <- function (x) ave(x, cumsum(x==0), FUN = seq_along) - 1
fun_dt <- function (x) rowid(rleid(x)) * x
run <- function(x) {
out <- streak_run(x)
out[x == 0] <- 0
out
}
microbenchmark::microbenchmark(
run,
fun_ave(x),
fun_dt(x),
times = 1000L
)
# Unit: nanoseconds
# expr min lq mean median uq max neval
# run 48 58.5 197.676 207.5 250.0 12599 1000
# fun_ave(x) 122984 137144.0 173577.501 146211.5 193241.5 3243640 1000
# fun_dt(x) 24954 28959.0 42959.954 36262.5 40843.0 4141624 1000