检查R中数据帧中NA的起始和结束索引

时间:2018-06-05 11:25:06

标签: r

我有一个列名为sorted_no的数据框,如下所示

x_n$sorted_no
1  2 NA  3  4 NA NA NA NA NA NA NA  5 NA NA NA NA  6 NA NA NA NA NA  7

我希望此列中的NA值的起始和结束索引如下所示

start end
  2    4
  5   13
 13   18
 18   24

3 个答案:

答案 0 :(得分:4)

在基地R

vec <- scan(text="1  2 NA  3  4 NA NA NA NA NA NA NA  5 NA NA NA NA  6 NA NA NA NA NA  7", what=numeric())

diff_vec <- diff(is.na(c(0,vec)))
# [1]  0  0  1 -1  0  1  0  0  0  0  0  0 -1  1  0  0  0
# [18] -1  1  0  0  0  0 -1

data.frame(start= which(diff_vec==1)-1,
           end= which(diff_vec==-1))

#   start end
# 1     2   4
# 2     5  13
# 3    13  18
# 4    18  24

0中的c(0,vec)有助于我们确保不会以NA

开头

data.table::rleidtapply的另一种解决方案:

library(data.table)
do.call(rbind,
        tapply(seq_along(vec)[is.na(vec)],rleid(vec)[is.na(vec)],
               function(x) data.frame(start=min(x)-1,end=max(x)+1)))

#    start end
# 3      2   4
# 6      5  13
# 8     13  18
# 10    18  24

在这里,我使用rleid创建群组,seq_along创建索引,在这些群组中,我使用minmax索引。

使用rle的基础解决方案:

vec[is.na(vec)] <- Inf
rle_    <- rle(vec)
cumsum_ <- cumsum(rle_$lengths)
infs_   <- which(rle_$value == Inf)
data.frame(start = c(0,cumsum_)[infs_], end = cumsum_[infs_]+1)

#   start end
# 1     2   4
# 2     5  13
# 3    13  18
# 4    18  24

base::rleNAs给予特殊处理,而data.table::rleid没有,因此我使用Inf,使其不那么健壮。

答案 1 :(得分:0)

data.table解决方案:

数据:

x<-scan(text="1  2 NA  3  4 NA NA NA NA NA NA NA  5 NA NA NA NA  6 NA NA NA NA NA  7", what=numeric()) 

代码:

data.table(x,rleid(is.na(x)),seq_along(x))[is.na(x),.(start=V3[1]-1,end=V3[1]+.N),by=V2][,-1]

#   start end
#1:     2   4
#2:     5  13
#3:    13  18
#4:    18  24

答案 2 :(得分:0)

另一个基础R解决方案:

which_na <- which(is.na(x_n$sorted_no))
which_notna <- which(!is.na(x_n$sorted_no))
data.frame(
  start = intersect(which_na - 1L, which_notna),
  end = intersect(which_na + 1L, which_notna)
)
  start end
1     2   4
2     5  13
3    13  18
4    18  24

再一次,玩rle()(灵感来自Mudskipper):

r <- rle(is.na(x_n$sorted_no))
data.frame(
  start = cumsum(r$lengths)[r$values] + 1,
  end = head(cumsum(r$lengths)[!r$values], sum(r$values))
)