如何用缺失的前后值的平均值填充向量中的缺失值

时间:2020-02-14 11:03:14

标签: r missing-data imputation imputets

目前,我正在尝试在R中的向量中估算值。 归因于。

  • 查找所有NA值
  • 然后检查它们前后是否具有现有值
  • 还要检查NA后面的值是否大于 NA之前的值
  • 如果满足条件,请使用之前的值计算平均值 之后。
  • 用估算值代替NA值
# example one
input_one = c(1,NA,3,4,NA,6,NA,NA)

# example two
input_two = c(NA,NA,3,4,5,6,NA,NA)

# example three
input_three = c(NA,NA,3,4,NA,6,NA,NA)

我开始编写代码以检测可以 被推算。但是我坚持以下几点。

# incomplete function to detect the values
sapply(split(!is.na(input[c(rbind(which(is.na(c(input)))-1, which(is.na(c(input)))+1))]), 
             rep(1:(length(!is.na(input[c(which(is.na(c(input)))-1, which(is.na(c(input)))+1)]))/2), each = 2)), all)

但是,这仅检测到可能是 可归因的,并且仅适用于示例一。它不完整且 不幸的是,它很难阅读和理解。

任何对此的帮助将不胜感激。

4 个答案:

答案 0 :(得分:1)

我们可以使用dplyr的{​​{1}}和lag函数:

lead

拒绝:

input_three = c(NA,NA,3,4,NA,6,NA,NA)

library(dplyr)
ifelse(is.na(input_three) & lead(input_three) > lag(input_three),
       (lag(input_three)  + lead(input_three))/ 2,
       input_three)

编辑

说明:

我们使用[1] NA NA 3 4 5 6 NA NA 的向量化版本ifelse。即if中的所有内容都将应用于向量的每个元素。 首先,我们测试元素是否为ifelse,以及后面的元素是否大于前一个元素。要获取上一个和下一个元素,我们可以使用NA dplyrlead函数:

lag使向量向右偏移(默认为1步):

lag

返回:

lag(1:5)

[1] NA 1 2 3 4 将向量向左偏移:

lead

返回:

lead(1:5)

现在进入[1] 2 3 4 5 NA 的'test'子句:

ifelse

哪个返回:

is.na(input_three) & lead(input_three) > lag(input_three)

然后,如果[1] NA NA FALSE FALSE TRUE FALSE NA NA 子句的值为ifelse,我们要返回上一个元素和下一个元素的和除以2,否则返回原始元素

答案 1 :(得分:1)

下面是使用imputeTS库的示例。它考虑了序列中的多个NA,如果下一个有效观测值大于最后一个有效观测值,则确保计算平均值,并且在开始和结束时都忽略NA

library(imputeTS)
myimpute <- function(series) {
    # Find where each NA is
    nalocations <- is.na(series)
    # Find the last and the previous observation for each row
    last1 <- lag(series)
    next1 <- lead(series)
    # Carry forward the last and next observations over sequences of NA
    # Each row will then get a last and next that can be averaged
    cflast <- na_locf(last1, na_remaining = 'keep')
    cfnext <- na_locf(next1, option = 'nocb', na_remaining = 'keep')
    # Make a data frame 
    df <- data.frame(series, nalocations, last1, cflast, next1, cfnext)
    # Calculate the mean where there is currently a NA
    # making sure that the next is greater than the last
    df$mean <- ifelse(df$nalocations, ifelse(df$cflast < df$cfnext, (df$cflast+df$cfnext)/2, NA), NA)
    imputedseries <- ifelse(df$nalocations, ifelse(!is.na(df$mean), df$mean, NA), series)
    #list(df,  imputedseries) # comment this in and return it to see the intermediate data frame for debugging
    imputedseries
}
myimpute(c(NA,NA,3,4,NA,NA,6,NA,NA,8,NA,7,NA,NA,9,NA,11,NA,NA))

# [1] NA NA  3  4  5  5  6  7  7  8 NA  7  8  8  9 10 11 NA NA

答案 2 :(得分:0)

以下是使用zoo::rollapply()的替代方法:

library(zoo)

fill_sandwiched_na <- function(f) rollapply(f, 3, FUN = function(x) {
  y <- mean(x[-2]); if(is.na(y)) x[2] else y
}, fill = NA, partial = TRUE)

fill_sandwiched_na(input_one)
[1]  1  2  3  4  5  6 NA NA

fill_sandwiched_na(input_two)
[1] NA NA  3  4  5  6 NA NA

fill_sandwiched_na(input_three)
[1] NA NA  3  4  5  6 NA NA

答案 3 :(得分:0)

imputeTS 软件包中还包含na_ma函数,用于估算移动平均值。

在您的情况下,将使用以下设置:

na_ma(x, k = 1, weighting = "simple")

  • k = 1(表示考虑NA之前的1值和NA之后的1)
  • weighting =“ simple”(计算这两个值的平均值)

基本上只需一行代码即可轻松实现:

library(imputeTS)
na_ma(yourData, k = 1, weighting = "simple") 

您还可以选择在NA之前和之后考虑更多的值,例如k = 3。如果您考虑到每一侧的值都超过1,则有趣的功能是可以选择其他权重,例如权重=“线性”时,权重在算术级数中减少(线性加权移动平均值)-表示它们的值越远离NA,其影响就越小。