Как извлечь специфические строки из фрейма данных - PullRequest
0 голосов
/ 18 июня 2019

Предположим, у меня достаточно большой фрейм данных, содержащий около миллиона строк

И я хочу удалить строки между BSM и ENDBSM в фрейме данных, как я могу сделать это эффективно?

Я думал, чтосначала пометьте строки 1, которые мне нужно извлечь, используя следующий цикл, но это займет вечность.

chkSTR = 0
for(i in 1:nrow(rDATA)){

  if(rDATA$Data[i] == "BSM"){
    chkSTR = 1
  }

  if(rDATA$Data[i] == "ENDBSM"){
    chkSTR = 0
  }

  rDATA$BOOL[i] = chkSTR

}

Пример кадра входных данных

rData = data.frame(

Data = 

c(1,"BSM","a",3,3,"ENDBSM",1,3,1,"BSM","b",3,3,"ENDBSM",1,2,1,"BSM","c",2,3,"ENDBSM",1,2)

)


Output example

rData = data.frame(

Data = 

c("BSM","a",3,3,"ENDBSM","BSM","b",3,3,"ENDBSM","BSM","c",2,3,"ENDBSM")

)

Ответы [ 3 ]

4 голосов
/ 18 июня 2019

Как уже упоминалось в комментариях, число "BSM" из "ENDBSM" одинаково и "BSM" всегда идет первым, мы можем использовать mapply и создать последовательность между индексами для подмножества.

rData[c(mapply(`:`, which(rData$Data == "BSM"), 
                    which(rData$Data == "ENDBSM"))), , drop = FALSE]
#    Data
#2     BSM
#3       a
#4       3
#5       3
#6  ENDBSM
#10    BSM
#11      b
#12      3
#13      3
#14 ENDBSM
#18    BSM
#19      c
#20      2
#21      3
#22 ENDBSM
1 голос
/ 19 июня 2019

Вы можете использовать Reduce, чтобы сделать триггер между BSM и ENDBSM.Не нужно, чтобы количество BSM и ENDBSM было одинаковым, и нет необходимости, чтобы BSM шел первым.Он просто включается, когда приходит BSM, и выключается, когда приходит ENDBSM.

idx <- Reduce(function(y,x) {(y || x=="BSM") && x!= "ENDBSM"}, x=rData$Data, init=FALSE, accumulate=TRUE)
rData[idx[-1] | idx[-length(idx)], , drop = FALSE]
#     Data
#2     BSM
#3       a
#4       3
#5       3
#6  ENDBSM
#10    BSM
#11      b
#12      3
#13      3
#14 ENDBSM
#18    BSM
#19      c
#20      2
#21      3
#22 ENDBSM

Если вы хотите избавиться от окружающих BSM и ENDBSM, вы можете сделать это с помощью:

rData[idx[-1] & idx[-length(idx)], , drop = FALSE]
#   Data
#3     a
#4     3
#5     3
#11    b
#12    3
#13    3
#19    c
#20    2
#21    3
1 голос
/ 18 июня 2019

Мы можем использовать map2 от purrr

library(purrr)
map2(which(rData$Data == "BSM"), which(rData$Data == "ENDBSM"), `:`) %>%
     flatten_int %>%
     extract2(rData, ., )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...