1. ホーム
  2. r

[解決済み] NAを最新の非NA値で置き換える

2022-04-21 03:12:29

質問

での data.frame (または data.table のように、NAを最も近い以前の非NA値で前方に埋めたいのです。簡単な例では、ベクトルを使って、( data.frame )は以下の通りです。

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

機能を希望する fill.NAs() を構築することができます。 yy というような。

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

この操作を、多数の(合計〜1Tb)小さなサイズの data.frame s (~30-50 Mb) で、行はそのすべてのエントリが NA である。この問題にアプローチする良い方法は何ですか?

私が考えた醜い解決策は、この関数を使っています。

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
}

機能 fill.NAs は以下のように使用します。

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]
} 

出力

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

...これは動作するようです。しかし、これは醜いです。何か提案はありますか?

解決方法は?

を使いたいのでしょう。 na.locf() の関数は 動物園 パッケージから 最後の観測を引き継ぐ を使用して、NA 値を置き換えます。

ヘルプにある使用例の冒頭部分を紹介します。

library(zoo)

az <- zoo(1:6)

bz <- zoo(c(2,NA,1,4,5,2))

na.locf(bz)
1 2 3 4 5 6 
2 2 1 4 5 2 

na.locf(bz, fromLast = TRUE)
1 2 3 4 5 6 
2 1 1 4 5 2 

cz <- zoo(c(NA,9,3,2,3,2))

na.locf(cz)
2 3 4 5 6 
9 3 2 3 2