Получите вектор с количеством последовательных определенных значений в R

У меня есть кадр данных, который выглядит так:

    (TimeDate,Movement,Booked)

    1   2017-01-02 09:00:13 FALSE   TRUE
    2   2017-01-02 09:01:13 FALSE   TRUE
    3   2017-01-02 09:02:15 TRUE    TRUE
    4   2017-01-02 09:03:13 TRUE    TRUE
    5   2017-01-02 09:04:13 FALSE   FALSE
    6   2017-01-02 09:05:13 FALSE   FALSE
    7   2017-01-02 09:06:13 FALSE   TRUE
    8   2017-01-02 09:07:13 FALSE   TRUE
    9   2017-01-02 09:08:14 TRUE    TRUE
    10  2017-01-02 09:09:13 FALSE   TRUE

Он имеет поминутный журнал с двумя логическими значениями, соответствующими обнаруженному движению и забронированному номеру. Я хочу получить вектор, который подсчитывает последовательные вхождения (FALSE, TRUE) для сообщений Movement и Booked, поэтому в этом случае мне нужен результирующий вектор, подобный этому:

    c(2,2,1)

Где первый элемент — это количество строк 1 и 2, второй — строк 7 и 8, а последний — строки 10.

Честно говоря, я даже не знаю, с чего начать. Спасибо!


person Santiago Alvarez    schedule 31.05.2020    source источник


Ответы (3)


Изменить: не видел идентичного решения Романа при публикации.

Мы хотели бы что-то вроде:

tmp <- rle(with(df, !Movement & Booked))
tmp$lengths[tmp$values]

Индексация по tmp$values гарантирует, что вы получите только строки, соответствующие указанному шаблону.

Надеюсь это поможет!

person infinitefactors    schedule 31.05.2020

Как насчет этого? Для каждой строки убедитесь, что вы получили правильную последовательность, а затем используйте rle.

xy <- read.table(text = "FALSE   TRUE
FALSE   TRUE
TRUE    TRUE
TRUE    TRUE
FALSE   FALSE
FALSE   FALSE
FALSE   TRUE
FALSE   TRUE
TRUE    TRUE
FALSE   TRUE", header = FALSE)
colnames(xy) <- c("Movement", "Booked")

out <- rle(apply(xy, MARGIN = 1, FUN = function(x) !isTRUE(x[1]) & isTRUE(x[2])))
out$lengths[out$values == TRUE]

[1] 2 2 1

Другим более простым вариантом будет

out <- rle(xy$Movement == FALSE & xy$Booked == TRUE)
out$lengths[out$values == TRUE]
person Roman Luštrik    schedule 31.05.2020

Вот один из вариантов с rleid, где мы создаем столбец группировки на основе FALSE в «Movement» и Booked TRUE, получаем count столбца

library(dplyr)
library(data.table)
df1 %>%
     mutate(rl = rleid(!Movement, Booked)) %>%
     filter(!(! Movement & Booked)) %>% 
     count(rl) %>%
     pull(n)
#[1] 2 2 1

Или с rle от base R

with(df1, with(rle(paste(Movement, Booked)), lengths[values == 'FALSE TRUE']))
#[1] 2 2 1

или используя компактный способ

with(df1, table(rleid(Movement, Booked)[!Movement & Booked]))

#1 4 6 
#2 2 1 

данные

df1 <- structure(list(TimeDate = c("2017-01-02 09:00:13", "2017-01-02 09:01:13", 
"2017-01-02 09:02:15", "2017-01-02 09:03:13", "2017-01-02 09:04:13", 
"2017-01-02 09:05:13", "2017-01-02 09:06:13", "2017-01-02 09:07:13", 
"2017-01-02 09:08:14", "2017-01-02 09:09:13"), Movement = c(FALSE, 
FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE), 
    Booked = c(TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, 
    TRUE, TRUE)), class = "data.frame", row.names = c("1", "2", 
"3", "4", "5", "6", "7", "8", "9", "10"))
person akrun    schedule 31.05.2020