Мы можем использовать data.table
методы для этого.Преобразуйте data.frame в data.table (setDT(df1)
), сгруппированные по id, выполните цикл по результату, rep
лицензируйте элементы с указанием последовательности из 1:.N
и .N:1
с NA в качестве отступа, затем объедините с исходным набором данных в столбцах 'id' и 't'
library(data.table)
df2 <- setDT(df1)[, Map(function(x, y, z) rep(c(NA, x),
c(y, z)), outcome, 1:.N, .N:1), id][, t := rowid(id)]
out <- df2[df1, on = .(id, t)]
setcolorder(out, c(1, 7, 8, 2:6))
setnames(out, 4:ncol(out), paste0("outcome_t", 1:5))
out
# id t outcome outcome_t1 outcome_t2 outcome_t3 outcome_t4 outcome_t5
# 1: 1 1 10 NA NA NA NA NA
# 2: 1 2 20 10 NA NA NA NA
# 3: 1 3 30 10 20 NA NA NA
# 4: 1 4 40 10 20 30 NA NA
# 5: 1 5 40 10 20 30 40 NA
# 6: 2 1 20 NA NA NA NA NA
# 7: 2 2 30 20 NA NA NA NA
# 8: 2 3 40 20 30 NA NA NA
# 9: 2 4 40 20 30 40 NA NA
#10: 2 5 20 20 30 40 40 NA
или опцию с dcast
dcast(setDT(df1), id + t ~ paste0("outcome_t", t),
value.var = 'outcome')[, na.locf(.SD, na.rm = FALSE), id]
Или мы можем сделать это более компактно
library(zoo)
nm1 <- paste0("outcome_t", 1:5)
df1[nm1] <- do.call(rbind, lapply(split(df1$outcome, df1$id),
function(x) head(rbind(NA, na.locf((NA^!diag(x)) * x)), -1)))
Или используя colCumsums
library(matrixStats)
df1[nm1] <- do.call(rbind, lapply(split(df1$outcome, df1$id),
function(x) colCumsums(rbind(0, diag(x)))[-length(x), ]))
data
df1 <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L),
t = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L), outcome = c(10L,
20L, 30L, 40L, 40L, 20L, 30L, 40L, 40L, 20L)),
class = "data.frame", row.names = c(NA, -10L))