首页 > 解决方案 > 通过平滑峰值填充 NA

问题描述

df <- data.frame(date = seq(from=as.POSIXct(as.Date("2020-10-01")), 
                            to= as.POSIXct(as.Date("2020-10-02")) , by = 'hour'), 
               val = c(15,20,18,22,17,NA,NA,NA,80,14,23,16,19,21,NA,NA,60,18,15,20,22,19,NA,35,18))

'NA' 的序列不均匀,后跟峰值,例如: val = 80, 60 和 35 。

我想通过平滑峰值来填充“NA”。例如:在第一个 NA 序列中,三个 NA 后面跟着 80,这等于四个数据点,因此,80 除以 4 = 20 。

注意:峰值不是异常值,因此数据点的总和不应改变。

如果可能的话,我想用上述条件填充 NA,同时保留信号行为(趋势和季节性)。

非常感谢。

标签: r

解决方案


以下函数NA用下一个非NA值除以序列长度填充值序列。

fill_na <- function(x){
  na <- is.na(x)
  r <- rle(na)
  div <- r$lengths[r$values] + 1L
  cs <- cumsum(r$lengths)[r$values]
  for(i in seq_along(div)){
    if(cs[i] < length(x)){
      x[ (cs[i] - div[i] + 1L):(cs[i] + 1L) ] <- x[ cs[i] + 1L ]/div[i]
    }
  }
  x
}

fill_na(df$val)
# [1] 15.0 20.0 18.0 22.0 20.0 20.0 20.0 20.0 20.0 14.0 23.0
#[12] 16.0 19.0 20.0 20.0 20.0 20.0 18.0 15.0 20.0 22.0 17.5
#[23] 17.5 17.5 18.0

推荐阅读