【问题标题】:propagating data within a vector在向量中传播数据
【发布时间】:2010-12-19 10:56:38
【问题描述】:

我正在学习 R,我很好奇……我需要一个函数来做这个:

> fillInTheBlanks(c(1, NA, NA, 2, 3, NA, 4))
[1] 1 1 1 2 3 3 4
> fillInTheBlanks(c(1, 2, 3, 4))
[1] 1 2 3 4

我制作了这个......但我怀疑还有更多 R 方法可以做到这一点。

fillInTheBlanks <- function(v) {
  ## replace each NA with the latest preceding available value

  orig <- v
  result <- v
  for(i in 1:length(v)) {
    value <- v[i]
    if (!is.na(value))
      result[i:length(v)] <- value
  }
  return(result)
}

【问题讨论】:

    标签: r vector


    【解决方案1】:

    zoo有一个函数na.locf()

    R> library("zoo")
    R> na.locf(c(1, 2, 3, 4))
    [1] 1 2 3 4
    R> na.locf(c(1, NA, NA, 2, 3, NA, 4))
    [1] 1 1 1 2 3 3 4
    

    na.locf:最后的观察结果; 用于将每个“NA”替换为之前的最新非“NA”的通用函数。

    查看函数na.locf.default的源代码,它不需要for-loop。

    【讨论】:

    • 及其 fromLast 参数解决了对称问题! (我现在正在看na.locf.R的代码,里面有很多值得一读的东西)
    • 有趣的来源。我正在添加另一个答案,从你和动物园图书馆中提炼出来。
    【解决方案2】:

    我正在从动物园图书馆做一些最小的复制和粘贴(再次感谢 rcs 指点我),这是我真正需要的:

    fillInTheBlanks <- function(S) {
      ## NA in S are replaced with observed values
    
      ## accepts a vector possibly holding NA values and returns a vector
      ## where all observed values are carried forward and the first is
      ## also carried backward.  cfr na.locf from zoo library.
      L <- !is.na(S)
      c(S[L][1], S[L])[cumsum(L)+1]
    }
    

    【讨论】:

      【解决方案3】:

      只是为了好玩(因为它比fillInTheBlanks 慢),这是一个依赖rle 函数的na.locf 版本:

      my.na.locf <- function(v,fromLast=F){
        if(fromLast){
          return(rev(my.na.locf(rev(v))))
        }
        nas <- is.na(v)
        e <- rle(nas)
        v[nas] <- rep.int(c(NA,v[head(cumsum(e$lengths),-1)]),e$lengths)[nas]
        return(v)
      }
      

      例如

      v1 <- c(3,NA,NA,NA,1,2,NA,NA,5)
      v2 <- c(NA,NA,NA,1,7,NA,NA,5,NA)
      
      my.na.locf(v1)
      #[1] 3 3 3 3 1 2 2 2 5
      
      my.na.locf(v2)
      #[1] NA NA NA  1  7  7  7  5  5
      
      my.na.locf(v1,fromLast=T)
      #[1] 3 1 1 1 1 2 5 5 5
      
      my.na.locf(v2,fromLast=T)
      #[1]  1  1  1  1  7  5  5  5 NA
      

      【讨论】:

        【解决方案4】:

        另一个简单的答案。这个处理第一个值是 NA。这是一个死胡同,所以我的循环统计来自索引 2。

        my_vec <- c(1, NA, NA, 2, 3, NA, 4)
        fill.it <- function(vector){
          new_vec <- vector
          for (i in 2:length(new_vec)){
            if(is.na(new_vec[i])) {
              new_vec[i] <- new_vec[i-1]
            } else {
              next
            }
          } 
          return(new_vec)
        }
        

        【讨论】:

          【解决方案5】:

          多个 R 包都包含一个 na.locf 函数,它正是这样做的。 (imputeTS、动物园、时空……)

          这里是 imputeTS 的一个例子:

          library("imputeTS")    
          x <- c(1, NA, NA, 2, 3, NA, 4)
          na.locf(x)
          

          imputeTS 包还提供了更高级的替换缺失值的方法。 (还有动物园)

          【讨论】:

            猜你喜欢
            • 2020-11-30
            • 2011-06-11
            • 2018-04-23
            • 1970-01-01
            • 2023-04-08
            • 1970-01-01
            • 2015-12-05
            • 1970-01-01
            • 2011-01-09
            相关资源
            最近更新 更多