Here is the vector option
vec_fun <- function(x, z) { L <- length(x) vec_z <- rep(0, L) I <- seq(2, L, by=2) vec_z[I] <- head(zc(0, cumsum(I)), length(I)) cumsum(vec_z) }
Alternative versions - sapply and tidyverse
sapply_fun <- function(x, z) { y=0 sapply(df$x,function(x)ifelse(x%%2==0,{y<<-y+z;z<<-zx;y},y<<-y)) } library(tidyverse) library(tidyverse) tidy_fun <- function(df) { df %>% filter(x %% 2 != 0) %>% mutate(z = accumulate(c(z, x[-1] - 1), `-`)) %>% right_join(df, by = c("x", "y")) %>% mutate(z = lag(z), z = ifelse(is.na(z), 0, z)) %>% mutate(y = cumsum(z)) %>% select(-z) %>% pluck("y") }
Your data
df <- data.frame(x=1:5, y=0) z <- 10
Let them all return the same result.
identical(vec_fun(df$x, z), sapply_fun(df$x, z), tidy_fun(df))
Benchmark with a small data set - sapply_fun looks a little faster
library(microbenchmark) microbenchmark(vec_fun(df$x, z), sapply_fun(df$x, z), tidy_fun(df), times=100L, unit="relative")
Now with a large data.frame
df <- data.frame(x=1:1000, y=0) z <- 10000
The same result - yes
identical(vec_fun(df$x, z), sapply_fun(df$x, z), tidy_fun(df))
Large dataset benchmark - now it's obvious vec_fun faster
library(microbenchmark) microbenchmark(vec_fun(df$x, z), sapply_fun(df$x, z), tidy_fun(df), times=100L, unit="relative")