Я не знаю, как избежать цикла, но вы можете использовать его внутри data.table, и я думаю, что он все равно будет эффективен:
### DT re-created with the following code
DT <- data.table(
name = c("Anna","Anna","Anna","Jenny","Jenny","Jenny","Jenny"),
id = c(100L,100L,100L,250L,250L,250L,250L),
time = as.Date(c("2000-01-01","2000-02-01","2000-03-01","2008-01-01","2008-02-01",
"2008-03-01","2008-04-01")),
start = c(100,100,100,200,200,200,200),
rate = c(4,4,4,5,5,5,5),
payment = c(15,20,25,10,20,30,35))
###
computeNewVar <- function(subDT){
v <- subDT$start
if(nrow(subDT)>1){
for(i in 2:nrow(subDT)){
v[i] <- v[i-1] * (1+subDT$rate[i]) - subDT$payment[i]
}
}
v
}
DT[,new_var:=computeNewVar(.SD),by=.(name,id)]
Результат:
> DT
name id time start rate payment new_var
1: Anna 100 2000-01-01 100 4 15 100
2: Anna 100 2000-02-01 100 4 20 480
3: Anna 100 2000-03-01 100 4 25 2375
4: Jenny 250 2008-01-01 200 5 10 200
5: Jenny 250 2008-02-01 200 5 20 1180
6: Jenny 250 2008-03-01 200 5 30 7050
7: Jenny 250 2008-04-01 200 5 35 42265