Or you can create your own vectorized version of na.approx
without any complicated loops and solve it without any external packages
myna.approx <- function(x){
len <- length(x)
cumsum(c(x[1L], rep((x[len] - x[1L])/(len - 1L), len - 1L)))
}
with(df, ave(value, id, FUN = myna.approx))
## [1] 100 250 400 550 300 500 700 900