【问题标题】:Fill NA's at boundary of a vector in r在 r 中的向量边界处填充 NA
【发布时间】:2020-03-06 12:06:11
【问题描述】:

我有一个在边界处包含 NA 的向量

x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)

我希望结果是:

c(-3, -1, 1,-1, 1, 0, -1, 2, 5, 8)

换句话说,我想用线性插值填充内部和边界 NA(也许我不能称之为“inter-polation”,因为 NA 在边界处)。

我尝试了包“zoo”中的一个函数,na.fill(x,“extend”),但边界输出不是我想要的,它只是重复最左边或最右边的非NA值:

na.fill(x,"extend")

输出是

[1] -1 -1  1 -1  1  0 -1  2  2  2

我还检查了其他用于填充 NA 的函数,例如 na.approx()、na.locf() 等,但它们都不起作用。

na.spline 确实有效,但边界 NA 的输出会导致非常大的变化。

na.spline(x)

输出是:

 [1] -15.9475983  -1.0000000   1.0000000  -1.0000000   1.0000000   0.3400655  -1.0000000   2.0000000
 [9]  13.1441048  35.9323144

边界点太大。谁能帮我吗?提前致谢!

【问题讨论】:

  • 我怀疑是否会有满足您期望的现有答案。您似乎希望使用内部 NA 的侧翼非缺失值的方法以及两个相邻非缺失值的差异来扩展末端的 NA 位置。这不是一个真正的标准程序,所以我认为如果你想要一个准确的响应,你需要更仔细地指定规则......也就是说,如果我对要使用的规则的猜测是正确的。
  • 你是对的。我想要的是填充 NA 现有的内部和外部位置(即边界点)。 1)对于内部点,使用线性插值是合理的,可以在几个包中找到。 2)但是,对于外部点,我没有找到标准解决方案,所以我建议使用类似于“线性插值”的方法,使用来自最近的两个非 NA 数据点的信息。这种方法肯定不够合理。
  • ...另请参阅上面的链接:“我想根据之前/之后的两个观察结果使用线性近似来推断边界 [..]”,由zoo的作者回答。

标签: r na zoo linear-interpolation


【解决方案1】:

您可以使用zoo 库中的na.spline()

na.spline(x)

[1] 0.0 0.5 1.0 1.5 2.0 2.5

原始问题的数据:

x <- c(0, NA, 1, NA, 2, NA)

【讨论】:

  • 对不起,我没有把我的问题说得很清楚。你能检查我的问题的当前版本吗?谢谢!
  • 现在是一个完全不同的问题。将不得不考虑它。
【解决方案2】:

鉴于问题编辑后的数据和预期输出,我相信以下函数可以做到。它用approxfun填充内部NA,然后将极端情况一一处理。

na.extrapol <- function(y){
  x <- seq_along(y)
  f <- approxfun(x[!is.na(y)], y[!is.na(y)])
  y[is.na(y)] <- f(x[is.na(y)])
  r <- rle(is.na(y))
  if(r$values[1]){
    Y <- y[r$lengths[1] + 1:2]
    X <- seq_len(r$lengths[1])
    y[rev(X)] <- Y[1] - diff(Y)*X
  }
  n <- length(r$lengths)
  if(r$values[n]){
    s <- sum(r$lengths[-n])
    Y <- y[s - 1:0]
    X <- seq_len(r$lengths[n])
    y[s + X] <- Y[2] + diff(Y)*X
  }
  y
}

x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
na.extrapol(x)
#[1] -3 -1  1 -1  1  0 -1  2  5  8

x2 <- c(NA, NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
na.extrapol(x2)
#[1] -5 -3 -1  1 -1  1  0 -1  2  5  8

【讨论】:

    【解决方案3】:

    这是一种方法:

    首先,我们进行线性逼近,这将使我们得到所有 tail NA-s 从左到右:

    x <- na.approx(x, method = "constant", f = 0.5,na.rm = F)
    

    现在让我们找到非 NA 向量和相关的最左边和最右边的算术级数增量项:

    x_c <- x[!is.na(x)]
    left <- x_c[1] - x_c[2]
    right <- x_c[length(x_c)] - x_c[length(x_c) - 1]
    

    现在是时候用等差数列得到的数字填充左右NA-s了:

    ind_x<- which(!is.na(x))
    big_M <- 100
    
    x[(ind_x[length(ind_x)]):length(x)] <- seq(x[ind_x[length(ind_x)]],
                                               sign(right) * big_M,
                                               right)[1:(length(x) - ind_x[length(ind_x)] + 1)]
    x[ind_x[1]:1] <- seq(x[ind_x[1]],sign(left) * big_M,left)[1:ind_x[1]]
    y <- x
    

    其中big_M 是用户定义的大数,在给定基础数据的情况下,算术级数不会超过该数字。

    输入 - 输出:

    x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
    > y
     [1] -3 -1  1 -1  1  0 -1  2  5  8
    
    x <- c(NA,NA,NA, -1, 1,-1, 1, NA, -1, 2, NA, NA,NA)
    > y
     [1] -7 -5 -3 -1  1 -1  1  0 -1  2  5  8 11
    
    x <- c(NA,NA,NA, 5,1, 1,-1, 1, NA, -1, 2, NA, NA,NA)
    > y
     [1] 17 13  9  5  1  1 -1  1  0 -1  2  5  8 11
    

    【讨论】:

      【解决方案4】:

      除了考虑Hmisc::approxExtrap,另一种选择是使用lm,但它很可能比这里的其他选项慢

      x <- c(NA, -1, 1,-1, 1, NA, -1, 2, NA, NA)
      DF <- data.frame(i=seq_along(x), x)
      cc <- DF[complete.cases(DF),]
      DF$x <- approx(cc$i, cc$x, DF$i)$y
      hh <- head(cc, 2L)
      tt <- tail(cc, 2L)
      DF$x[DF$i < hh$i[1L]] <- predict(lm(x ~ i, hh), DF[DF$i < hh$i[1L], "i", drop=FALSE])
      DF$x[DF$i > tt$i[2L]] <- predict(lm(x ~ i, tt), DF[DF$i > tt$i[2L], "i", drop=FALSE])
      DF
      

      输出:

          i  x
      1   1 -3
      2   2 -1
      3   3  1
      4   4 -1
      5   5  1
      6   6  0
      7   7 -1
      8   8  2
      9   9  5
      10 10  8
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-19
        • 1970-01-01
        • 1970-01-01
        • 2020-09-28
        • 2014-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多