Here is another option using split
and cumsum
:
unlist(sapply(split(x, cumsum(x == FALSE)), cumsum), use.names = F)
# [1] 0 0 1 2 3 0 1 0 1 2 0
Benchmarking
Here are the microbenchmark
results of all solutions so far:
library(microbenchmark);
library(runner);
set.seed(2017);
x <- sample(c(TRUE, FALSE), 10^4, replace = T);
microbenchmark(
cumsum_thelatemail = ave(x[x], cumsum(!x)[x], FUN=seq_along),
reduce_Onyambu = Reduce(function(a,b)ifelse(b==0,0,a)+b,x,accumulate = T),
rle_MrFlick = with(rle(x), unlist(Map(`*`, sapply(lengths, seq.int), values))),
runner_Gonzo = streak_run(x)*x,
sequence_Henrik = sequence(rle(x)$lengths) * x,
split_Evers = unlist(sapply(split(x, cumsum(x == FALSE)), cumsum), use.names = F)
)
#Unit: microseconds
# expr min lq mean median uq
# cumsum_thelatemail 3569.336 3713.939 4196.6491 3802.570 4115.896
# reduce_Onyambu 40599.427 41884.466 45887.2020 43222.302 49277.158
# rle_MrFlick 9349.131 9907.766 11353.1854 10602.481 11213.147
# runner_Gonzo 275.912 293.085 316.6987 295.656 300.059
# sequence_Henrik 2696.624 2840.593 3177.7400 2956.738 3179.673
# split_Evers 4772.078 4954.352 5423.3227 5193.803 5528.410
# max neval
# 11360.39 100
# 103999.41 100
# 46731.03 100
# 538.49 100
# 11670.56 100
# 13607.49 100