Trong data.frame (hoặc data.table), tôi muốn "điền vào" NA với giá trị không NA gần nhất trước đó. Một ví dụ đơn giản, sử dụng vectơ (thay vì a data.frame
) là như sau:
> y <- c(NA, 2, 2, NA, NA, 3, NA, 4, NA, NA)
Tôi muốn một chức năng fill.NAs()
cho phép tôi xây dựng yy
sao cho:
> yy
[1] NA NA NA 2 2 2 2 3 3 3 4 4
Tôi cần lặp lại thao tác này trong nhiều (tổng ~ 1 Tb) kích thước nhỏ data.frame
(~ 30-50 Mb), trong đó một hàng là NA là tất cả các mục nhập của nó. Một cách tốt để tiếp cận vấn đề là gì?
Giải pháp xấu xí tôi nấu lên sử dụng chức năng này:
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
}
Các chức năng fill.NAs
được sử dụng như sau:
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]
}
Đầu ra
> y
[1] NA 2 2 2 2 3 3 3 4 4 4
... có vẻ như hoạt động. Nhưng, người đàn ông, nó là xấu xí! Bất kỳ đề xuất?
fill
trongR
tidyr::fill()
.
roll=TRUE
trongdata.table
.