如何将NA值替换为先前非NA和下一个非NA值的平均值? 例如,我想将第一个NA值替换为-0.873,将第四个/第五个值替换为-0.497 + 53.200的平均值。
谢谢!
t <- c(NA, -0.873, -0.497, NA, NA, 53.200, NA, NA, NA, 26.100)
=================== ADD ON =================== 谢谢大家回答这个问题!回复晚了非常抱歉。这只是数据帧的一部分(10000 * 91),我只从第一列中取出前10行以简化问题。我认为大卫和MKR的结果是我应该拥有的。
答案 0 :(得分:2)
此函数根据滚动窗口中从第一个元素到下一个元素的非NA
值的平均值,在向量中计算NA
的值。
t <- c(NA, -0.873, -0.497, NA, NA, 53.200, NA, NA, NA, 26.100)
roll_impute <- function(x){
n <- length(x)
res <- x
for (i in seq_along(x)){
if (is.na(x[i])){
res[i] <- mean(rep_len(x, i+1), na.rm = TRUE )
}
}
if (is.na(x[n])) x[n] <- mean(x, na.rm = TRUE)
res
}
roll_impute(t)
# [1] -0.87300 -0.87300 -0.49700 -0.68500 17.27667 53.20000 17.27667 17.27667 19.48250
# [10] 26.10000
roll_impute()
包含在最终元素为NA
的情况下更正滚动窗口的代码,以便向量不被回收。在您的示例中不是这种情况,但是为了概括函数,需要它。对这个函数的任何改进都是受欢迎的:)它确实使用for循环,但不会增长任何向量。没有简单的方法来避免for循环并依赖于对象的结构现在跳到我的脑海。
答案 1 :(得分:2)
这是一种使用基础R的可能的矢量化方法(某些步骤可能会有所改进,但我现在没有时间研究它)
x <- c(NA, -0.873, -0.497, NA, NA, 53.200, NA, NA, NA, 26.100)
# Store a boolean vector of NA locaiotns for firther use
na_vals <- is.na(x)
# Find the NAs location compaed to the non-NAs
start_ind <- findInterval(which(na_vals), which(!na_vals))
# Createa right limit
end_ind <- start_ind + 1L
# Replace zero locations with NAs
start_ind[start_ind == 0L] <- NA_integer_
# Calculate the means and replace the NAs
x[na_vals] <- rowMeans(cbind(x[!na_vals][start_ind], x[!na_vals][end_ind]), na.rm = TRUE)
x
# [1] -0.8730 -0.8730 -0.4970 26.3515 26.3515 53.2000 39.6500 39.6500 39.6500 26.1000
这应适用于载体两侧的NA。
答案 2 :(得分:1)
基于dplyr
和tidyr
的解决方案可以是:
library(dplyr)
library(tidyr)
t <- c(NA, -0.873, -0.497, NA, NA, 53.200, NA, NA, NA, 26.100)
data.frame(t) %>%
mutate(last_nonNA = ifelse(!is.na(t), t, NA)) %>%
mutate(next_nonNA = ifelse(!is.na(t), t, NA)) %>%
fill(last_nonNA) %>%
fill(next_nonNA, .direction = "up") %>%
mutate(t = case_when(
!is.na(t) ~ t,
!is.na(last_nonNA) & !is.na(next_nonNA) ~ (last_nonNA + next_nonNA)/2,
is.na(last_nonNA) ~ next_nonNA,
is.na(next_nonNA) ~ last_nonNA
)
) %>%
select(t)
# t
# 1 -0.8730
# 2 -0.8730
# 3 -0.4970
# 4 26.3515
# 5 26.3515
# 6 53.2000
# 7 39.6500
# 8 39.6500
# 9 39.6500
# 10 26.1000
注意:它看起来有点复杂,但它可以解决问题。通过for循环可以实现相同的功能。