проверка начального и конечного индекса NA в кадре данных в R - PullRequest
0 голосов
/ 05 июня 2018

У меня есть датафрейм с именем столбца 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 голосов
/ 05 июня 2018

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
0 голосов
/ 05 июня 2018

Еще одно базовое решение 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))
)
0 голосов
/ 05 июня 2018

В базе 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::rleid и tapply:

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 для создания индексов, и среди этих групп я беру * min и max index.


Базовое решение с использованием 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::rle дает специальную обработку NAs, тогда как data.table::rleid нет, поэтому я использовалInf, делает его несколько менее устойчивым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...