【问题标题】:How to remove a tail with NA in r?如何在r中删除带有NA的尾巴?
【发布时间】:2019-04-10 20:01:26
【问题描述】:

我有一个向量:

a <- c(NA,1:5,NA,NA,1:3, rep(NA,round(runif(1,0,100))))

我需要删除结尾的NAs。期望的结果:

c(NA, 1:5, NA, NA, 1:3)

【问题讨论】:

标签: r na missing-data


【解决方案1】:

你可以的

a[1:max(which(!is.na(a)))]
# [1] NA  1  2  3  4  5 NA NA  1  2  3

我们从位置 1 到最后一个非 NA 值的向量子集。

【讨论】:

  • a 仅包含NA 时,这个失败(可能非常不可能)。
【解决方案2】:

一种选择是

a[rev(cumprod(rev(is.na(a)))) == 0]
# [1] NA  1  2  3  4  5 NA NA  1  2  3

步骤如下:

(a <- c(NA, 1:5, NA, NA, 1:3, NA, NA))
# [1] NA  1  2  3  4  5 NA NA  1  2  3 NA NA
is.na(a)
# [1]  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE
rev(is.na(a))
# [1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE
cumprod(rev(is.na(a)))
# [1] 1 1 0 0 0 0 0 0 0 0 0 0 0
rev(cumprod(rev(is.na(a))))
# [1] 0 0 0 0 0 0 0 0 0 0 0 1 1

【讨论】:

    【解决方案3】:

    您可以找到不是NA的最大位置和相应的子集

    > a[1:max(which(!is.na(a)))]
     [1] NA  1  2  3  4  5 NA NA  1  2  3
    

    【讨论】:

      【解决方案4】:

      还有一种可能:

      a[cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)]
      
       [1] NA  1  2  3  4  5 NA NA  1  2  3
      

      在个别步骤中:

      is.na(a)
      
       [1]  TRUE FALSE FALSE FALSE FALSE
      
      cumsum(!is.na(a))
      
       [1] 0 1 2 3 4
      
      cumsum(!is.na(a)) != max(cumsum(!is.na(a)))
      
       [1]  TRUE  TRUE  TRUE  TRUE  TRUE
      
      cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)
      
       [1]  TRUE  TRUE  TRUE  TRUE  TRUE
      

      只是为了好玩,一些基准测试:

      library(microbenchmark)
      
      a <- rep(a, 1e5)
      
       microbenchmark(
       markus = a[1:max(which(!is.na(a)))],
       Julius_Vainora = a[rev(cumprod(rev(is.na(a)))) == 0],
       Kim = rm_NA_tail(a),
       tmfmnk = a[cumsum(!is.na(a)) != max(cumsum(!is.na(a))) * is.na(a)],
       nsinghs = a[1:(length(a) - rle(is.na(rev(a)))$lengths[1])],
       times = 5
      )
      
      Unit: milliseconds
                 expr      min       lq     mean   median       uq       max neval cld
               markus 150.7346 153.0674 156.4194 153.3031 159.4718  165.5201     5 a  
       Julius_Vainora 393.8520 418.8186 616.3269 703.4022 749.6600  815.9018     5  bc
                  Kim 370.7680 382.1826 536.0828 632.0031 642.1882  653.2720     5  bc
               tmfmnk 390.2626 415.2378 466.4245 415.8310 423.3828  687.4082     5  b 
              nsinghs 537.0404 781.1403 798.6929 793.1027 842.6777 1039.5033     5   c
      

      【讨论】:

        【解决方案5】:

        我认为这可行:

        rm_NA_tail <- function(a) {
          if (is.na(a[length(a)])) {
            return(a[is.na(match(data.table::rleid(a), max(data.table::rleid(a))))])
          } else {
            return(a)
          }
        }
        

        【讨论】:

          【解决方案6】:

          这可以使用rle()来完成

          a[1:(length(a) - rle(is.na(rev(a)))$lengths[1])]
          #  [1] NA  1  2  3  4  5 NA NA  1  2  3
          

          rle(is.na(rev(a)))$lengths[1] 获取向量中尾随 NA 的计数,然后从总向量 length 中减去它,以获得您想要保持向量的索引。

          【讨论】:

            猜你喜欢
            • 2017-06-12
            • 2013-11-25
            • 1970-01-01
            • 2021-04-17
            • 2017-08-13
            • 2014-04-17
            • 2023-03-20
            • 2015-05-06
            • 2017-05-04
            相关资源
            最近更新 更多