I have a string of numbers:
n1 = c(1, 1, 0, 6, 0, 0, 10, 10, 11, 12, 0, 0, 19, 23, 0, 0)
I need to replace 0 with the corresponding number righ
Here's a solution using data.table
:
require(data.table) ## >= 1.9.2
idx = which(!n1 %in% 0L)
DT <- data.table(val=n1[idx], idx=idx)
setattr(DT, 'sorted', "idx")
n1 = DT[J(seq_along(n1)), roll=Inf]$val
# [1] 1 1 1 6 6 6 10 10 11 12 12 12 19 23 23 23
require(zoo)
require(data.table)
set.seed(1L)
n1 = sample(c(0:10), 1e6, TRUE)
## data.table
dt_fun <- function(n1) {
idx = which(!n1 %in% 0L)
DT <- data.table(val=n1[idx], idx=idx)
setattr(DT, 'sorted', "idx")
DT[J(seq_along(n1)), roll=Inf]$val
}
# na.locf from zoo - gagolews
zoo_fun <- function(n1) {
wh_na <- which(is.na(n1))
n1[n1 == 0] <- NA
n2 <- na.locf(n1)
n2[wh_na] <- NA
n2
}
## rle - thelatemail
rle_fun <- function(n1) {
r <- rle(n1)
r$values[which(r$values==0)] <- r$values[which(r$values==0)-1]
inverse.rle(r)
}
flodel_fun <- function(n1) n1[cummax(seq_along(n1) * (n1 != 0))]
require(microbenchmark)
microbenchmark(a1 <- dt_fun(n1),
a2 <- zoo_fun(n1),
a3 <- rle_fun(n1),
a4 <- flodel_fun(n1), times=10L)
Here's the benchmarking result:
# Unit: milliseconds
# expr min lq median uq max neval
# a1 <- dt_fun(n1) 155.49495 164.04133 199.39133 243.22995 289.80908 10
# a2 <- zoo_fun(n1) 596.33039 632.07841 671.51439 682.85950 697.33500 10
# a3 <- rle_fun(n1) 356.95103 377.61284 383.63109 406.79794 495.09942 10
# a4 <- flodel_fun(n1) 51.52259 55.54499 56.20325 56.39517 60.15248 10