【问题标题】:Replace NA with modified version of previous number in R vector用 R 向量中先前数字的修改版本替换 NA
【发布时间】:2021-06-04 12:47:59
【问题描述】:

我有一个带有一些 NA 的向量,我想用之前的非 NA 值减去 0.1 替换其中的一些 NA。如果 NA 字符串长于某个长度(例如,2),我也不想替换 NA。这是一个例子

x <- c(1:3, NA, 4, NA, NA, 5, NA, NA, NA, 6, NA)

我想制作一个看起来像这样的向量

x_prime <- c(1:3, 2.9, 4, 3.9, 3.8, 5, NA, NA, NA, 6, 5.9)

打印出来的样子如下:

> x_prime
 [1] 1.0 2.0 3.0 2.9 4.0 3.9 3.8 5.0  NA  NA  NA 6.0  5.9

作为一个额外的复杂因素,我想跟踪我修改的索引,所以我还想要一个看起来像的向量

idx <- c(4, 6, 7, 13)

如果在 NA 中的第一个位置(以及所有领先的 NA),我们可以离开它并且什么都不做。

我在 SO 上发现了一些类似的问题,例如this,并且我尝试了与那里提供的功能类似的功能,但没有成功。有任何想法吗?提前谢谢你。

【问题讨论】:

  • idx 表示要替换最后一个位置。但是x_prime 显示NA 而不是5.9。请澄清。 - 如果第一个位置是NA 并且没有先前的值,应该怎么办?请说明。
  • 为什么最后一个 NA 没有被 5.9 替换?它的长度小于2。
  • 我进行了编辑以解决此问题并解释说我们不需要更改领先的 NA

标签: r vector na missing-data


【解决方案1】:

这是diffcumsumsplit 的选项

library(zoo)
lst1 <- split(x, cumsum(c( diff(!is.na(x)) < 0, TRUE)))
unname(unlist(lapply(lst1, function(x) if(sum(is.na(x)) <= 2) 
      na.locf0(x) -seq(0, length.out = length(x), by = 0.1) else x)))
#[1] 1.0 1.9 3.0 2.9 4.0 3.9 3.8 5.0  NA  NA  NA 6.0  NA

对于第二种情况

as.vector(unlist(sapply(split(seq_along(x) * is.na(x), 
     cumsum(c( diff(!is.na(x)) < 0, TRUE))), 
         function(x)  x[x != 0 & sum(x != 0) <=2])))
#[1]  4  6  7 13

【讨论】:

    【解决方案2】:

    带有ave 的基本 R 选项:

    len <- 2
    x1 <- ave(x, cumsum(!is.na(x)), FUN = function(v) {
      if(length(v) > len + 1) v 
      else v[1] - seq(0, by= 0.1, length.out = length(v))
      })
    
    x1
    #[1] 1.0 2.0 3.0 2.9 4.0 3.9 3.8 5.0  NA  NA  NA 6.0 5.9
    

    我们将NA 值与第一个非NA 值一起创建组,并在ave 中使用它。如果组长度大于len + 1+ 1,因为每个组中的第一个值不是NA),那么我们不会更改组中的任何内容,否则我们从第一个值中减去 0、0.1、0.2组。


    要获得被替换的位置,找出x 中的NA,而不是x1 中的NA

    which(is.na(x) & !is.na(x1))
    #[1]  4  6  7 13
    

    【讨论】:

      【解决方案3】:

      使用包imputeTS 使用na_locf 和参数maxgap 的版本:

      library("imputeTS")
      x_prime <- na_locf(x, maxgap = 2)
      idx <- which(is.na(imp) != is.na(x))
      x_prime[idx] <- x_prime[idx] - 0.1
      

      结果:

      x_prime
      [1] 1.0 2.0 3.0 2.9 4.0 3.9 3.9 5.0  NA  NA  NA 6.0 5.9
      
      idx
      [1]  4  6  7 13
      

      编辑: 简短的补充,似乎我以不同的方式解释了“用以前的非 NA 值减去 0.1 替换 NA”。不确定它是否是故意的,但你似乎更喜欢负 0.1 也被完成,因为之前的值是一个推算值。

      【讨论】:

        猜你喜欢
        • 2011-10-04
        • 2017-08-11
        • 2012-11-10
        • 2020-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 1970-01-01
        相关资源
        最近更新 更多