Найдите длительность и создайте трэ sh, если разрыв превышает определенное время - PullRequest
1 голос
/ 01 апреля 2020

Цель:

У меня есть набор данных, df, который я хотел бы сгруппировать по идентификатору и найти продолжительность на основе определенных условий: Focus == True, Read == Правда и ID! = "". Однако я не хочу агрегировать идентификаторы, так как я sh хочу, чтобы они были в своих отдельных «блоках», я также хотел бы sh, чтобы создать порог, при котором, если время между ними превышает 4 минуты, для группировки эта временная метка отдельно, как показано ниже в выходных данных.

ID            Date                   Focus        Read


A             1/2/2020 5:00:00 AM    TRUE         TRUE
A             1/2/2020 5:00:05 AM    TRUE         TRUE
              1/3/2020 6:00:00 AM    TRUE
              1/3/2020 6:00:05 AM    TRUE         
B             1/4/2020 7:00:00 AM    TRUE         TRUE
B             1/4/2020 7:00:05 AM    TRUE         TRUE
B             1/4/2020 7:20:00 AM    TRUE         TRUE
B             1/4/2020 7:20:10 AM    TRUE         TRUE
A             1/2/2020 7:30:00 AM    TRUE         TRUE
A             1/2/2020 7:30:20 AM    TRUE         TRUE

Я хотел бы получить следующие выходные данные:

ID                          Duration              Start                    End

A                           5 sec                 1/2/2020 5:00:00 AM     1/2/2020 5:00:05 AM
B                           5 sec                 1/4/2020 7:00:00 AM     1/4/2020 7:00:05 AM    
B                           10 sec                1/4/2020 7:20:00 AM     1/4/2020 7:20:10 AM
A                           20 sec                1/2/2020 7:30:00 AM     1/2/2020 7:30:20 AM     

dput:

structure(list(ID = structure(c(2L, 2L, 1L, 1L, 3L, 3L, 3L, 3L, 
2L, 2L), .Label = c("", "A", "B"), class = "factor"), Date = structure(c(1L, 
2L, 5L, 6L, 7L, 8L, 9L, 10L, 3L, 4L), .Label = c("1/2/2020 5:00:00 AM", 
"1/2/2020 5:00:05 AM", "1/2/2020 7:30:00 AM", "1/2/2020 7:30:20 AM", 
"1/3/2020 6:00:00 AM", "1/3/2020 6:00:05 AM", "1/4/2020 7:00:00 AM", 
"1/4/2020 7:00:05 AM", "1/4/2020 7:20:00 AM", "1/4/2020 7:20:10 AM"
), class = "factor"), Focus = structure(c(1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L), .Label = "True ", class = "factor"), Read = structure(c(2L, 
2L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("", "True "), class = "factor")), class =    "data.frame", row.names = c(NA, 
-10L))

Это работает хорошо, но вместо того, чтобы объединять идентификаторы, как бы я держал их отдельно:

 library(dplyr)
 library(lubridate)
 df %>% 
 filter(as.logical(trimws(Read)), as.logical(trimws(Focus))) %>%
 mutate(Date = mdy_hms(Date)) %>%
 group_by(ID) %>% 
 summarise(Duration = difftime(last(Date), first(Date), units = "secs"))

Любое предложение приветствуется.

1 Ответ

2 голосов
/ 01 апреля 2020

Мы можем удалить пустые значения в Read и Focus, преобразовать Date, создать отдельные группы с порогом продолжительностью 4 минуты и получить разницу во времени между значениями last и first.

library(dplyr)

df %>% 
  filter(as.logical(trimws(Read)), as.logical(trimws(Focus))) %>%
  mutate(Date = lubridate::mdy_hms(Date)) %>% 
  group_by(grp = cumsum(abs(difftime(Date, lag(Date, 
                            default = first(Date)), units = "mins")) > 4)) %>%
  summarise(ID = first(ID),
            Duration = difftime(last(Date), first(Date), units = "secs"), 
            Start = first(Date), 
            End = last(Date)) %>%
  select(-grp)


#  ID    Duration Start               End                
#  <fct> <drtn>   <dttm>              <dttm>             
#1 A      5 secs  2020-01-02 05:00:00 2020-01-02 05:00:05
#2 B      5 secs  2020-01-04 07:00:00 2020-01-04 07:00:05
#3 B     10 secs  2020-01-04 07:20:00 2020-01-04 07:20:10
#4 A     20 secs  2020-01-02 07:30:00 2020-01-02 07:30:20
...