6.23 用最后一个非 NA 值填充 NA
6.23.1 问题
你想要将非 NA
值代替向量或者因子中的 NA
值。
6.23.2 方案
这段代码展示了如何填充向量中的空白。如果需要重复执行此操作,请参阅下面的函数。该函数还可以用第一个确定的值填充第一个即为NA
的情况,并正确处理因子。
# 示例数据
x <- c(NA, NA, "A", "A", "B", "B", "B", NA, NA, "C", NA,
NA, NA, "A", "A", "B", NA, NA)
goodIdx <- !is.na(x)
goodIdx
#> [1] FALSE FALSE TRUE TRUE TRUE TRUE TRUE FALSE
#> [9] FALSE TRUE FALSE FALSE FALSE TRUE TRUE TRUE
#> [17] FALSE FALSE
# 这些是来自x的非NA数值
# 加入领头的NA,后边会使用。用来进行索引
goodVals <- c(NA, x[goodIdx])
goodVals
#> [1] NA "A" "A" "B" "B" "B" "C" "A" "A" "B"
# 用来自输出向量的索引填充输出向量的索引
# 这些补偿了goodVals。加1是为了避免索引为0
fillIdx <- cumsum(goodIdx) + 1
fillIdx
#> [1] 1 1 2 3 4 5 6 6 6 7 7 7 7 8 9 10 10
#> [18] 10
# 原本向量的值被填充了
6.23.2.1 填充 NA 的函数
此函数执行与上面代码相同的操作。它还可以用第一个良好的值填充第一个就是NA
的情况,并正确处理因子。
fillNAgaps <- function(x, firstBack = FALSE) {
## 向量或因子中的 NA 被之前一个非 NA 值代替 如果
## firstBack 为 TRUE,将会对领头的 NA 填充第一个非 NA
## 值,否则不会
## 如果是一个因子,保存因子的水平,并转换为整数
lvls <- NULL
if (is.factor(x)) {
lvls <- levels(x)
x <- as.integer(x)
}
goodIdx <- !is.na(x)
# 这些是来自于x的非NA值
# 加入领头NA或者以第一个值代替,取决于firstBack参数
if (firstBack)
goodVals <- c(x[goodIdx][1], x[goodIdx]) else goodVals <- c(NA, x[goodIdx])
# 用来自输出向量的索引填充输出向量的索引
# 这些补偿了goodVals。加1是为了避免索引为0
fillIdx <- cumsum(goodIdx) + 1
x <- goodVals[fillIdx]
# 如果它最初是一个因子,那么将它转换回来
if (!is.null(lvls)) {
x <- factor(x, levels = seq_along(lvls), labels = lvls)
}
x
}
# 示例数据
x <- c(NA, NA, "A", "A", "B", "B", "B", NA, NA, "C", NA,
NA, NA, "A", "A", "B", NA, NA)
x
#> [1] NA NA "A" "A" "B" "B" "B" NA NA "C" NA NA
#> [13] NA "A" "A" "B" NA NA
fillNAgaps(x)
#> [1] NA NA "A" "A" "B" "B" "B" "B" "B" "C" "C" "C"
#> [13] "C" "A" "A" "B" "B" "B"
# 对领头的 NA 以第一个非 NA 值进行填充
fillNAgaps(x, firstBack = TRUE)
#> [1] "A" "A" "A" "A" "B" "B" "B" "B" "B" "C" "C" "C"
#> [13] "C" "A" "A" "B" "B" "B"
# 因子数据也能使用
y <- factor(x)
y
#> [1] <NA> <NA> A A B B B <NA> <NA> C
#> [11] <NA> <NA> <NA> A A B <NA> <NA>
#> Levels: A B C
fillNAgaps(y)
#> [1] <NA> <NA> A A B B B B B C
#> [11] C C C A A B B B
#> Levels: A B C
6.23.2.2 注释
改编自来自于 zoo 包的 na.locf()
函数。