Reemplazo de NA con el último valor que no sea de NA

En un data.frame (o data.table), me gustaría "completar" NA con el valor anterior que no sea NA más cercano. Un ejemplo simple, usando vectores (en lugar de unadata.frame) es el siguiente

> y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)

Me gustaría una funciónfill.NAs() que me permite construiryy tal que:

> yy
[1] NA NA NA  2  2  2  2  3  3  3  4  4

Necesito repetir esta operación para muchos (total ~ 1 Tb) de tamaño pequeñodata.frames (~ 30-50 Mb), donde una fila es NA, todas sus entradas son. ¿Cuál es una buena manera de abordar el problema?

La solución fea que preparé usa esta función:

last <- function (x){
    x[length(x)]
}    

fill.NAs <- function(isNA){
if (isNA[1] == 1) {
    isNA[1:max({which(isNA==0)[1]-1},1)] <- 0 # first is NAs 
                                              # can't be forward filled
}
isNA.neg <- isNA.pos <- isNA.diff <- diff(isNA)
isNA.pos[isNA.diff < 0] <- 0
isNA.neg[isNA.diff > 0] <- 0
which.isNA.neg <- which(as.logical(isNA.neg))
if (length(which.isNA.neg)==0) return(NULL) # generates warnings later, but works
which.isNA.pos <- which(as.logical(isNA.pos))
which.isNA <- which(as.logical(isNA))
if (length(which.isNA.neg)==length(which.isNA.pos)){
    replacement <- rep(which.isNA.pos[2:length(which.isNA.neg)], 
                                which.isNA.neg[2:max(length(which.isNA.neg)-1,2)] - 
                                which.isNA.pos[1:max(length(which.isNA.neg)-1,1)])      
    replacement <- c(replacement, rep(last(which.isNA.pos), last(which.isNA) - last(which.isNA.pos)))
} else {
    replacement <- rep(which.isNA.pos[1:length(which.isNA.neg)], which.isNA.neg - which.isNA.pos[1:length(which.isNA.neg)])     
    replacement <- c(replacement, rep(last(which.isNA.pos), last(which.isNA) - last(which.isNA.pos)))
}
replacement
}

La funciónfill.NAs se utiliza de la siguiente manera:

y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
isNA <- as.numeric(is.na(y))
replacement <- fill.NAs(isNA)
if (length(replacement)){
which.isNA <- which(as.logical(isNA))
to.replace <- which.isNA[which(isNA==0)[1]:length(which.isNA)]
y[to.replace] <- y[replacement]
} 

Salid

> y
[1] NA  2  2  2  2  3  3  3  4  4  4

... que parece funcionar. Pero, hombre, ¿es feo! ¿Alguna sugerencia

Respuestas a la pregunta(14)

Su respuesta a la pregunta