Как сгруппировать экземпляры времени, найти их продолжительность и суммировать их на основе определенных c условий (в R или Python) - PullRequest
0 голосов
/ 27 февраля 2020

Цель

У меня есть набор данных, который отслеживает, когда кто-то редактировал сообщение, ушел и вернулся, чтобы возобновить редактирование этого же сообщения. Я пытаюсь сгруппировать это сообщение и найти его общую продолжительность.

Проблема

Мне нужно сначала сгруппировать сообщение вместе, если применяются следующие условия: если Folder == 'out' ИЛИ drafts, Message == "", Edit == "T", и если содержимое столбцов Subject и Re последовательно совпадает.

В идеале это даст мне группу A вместе с ее продолжительностью , Например, этот первый «блок» данных будет помечен как «Группа A», будет иметь время начала 1/2/2020 1:00:01 AM и время окончания 1/2/2020 1:00:30 AM

Кроме того, я хотел бы «сопоставить» группу A с другим «блоком» данных, если последняя строка столбца Subject, Re и Length совпадает с ее первой строкой. Таким образом, вторая группа А будет иметь время начала 1/2/2020 1:02:00 AM и время окончания 1/2/2020 1:02:05 AM.

Subject Re                    Length         Folder      Message   Date                   Edit     
        a@mail.com,b@mail.com 80             out                   1/2/2020 1:00:01 AM     T                               
        a@mail.com,b@mail.com 80             out                   1/2/2020 1:00:05 AM     T                        
hey     a@mail.com,b@mail.com 80             out                   1/2/2020 1:00:10 AM     T                        
hey     a@mail.com,b@mail.com 80             out                   1/2/2020 1:00:15 AM     T                        
hey     a@mail.com,b@mail.com 80             out                   1/2/2020 1:00:30 AM     T 



hey     a@mail.com,b@mail.com 80            draft                  1/2/2020 1:02:00 AM     T                        
hey     a@mail.com,b@mail.com 80            draft                  1/2/2020 1:02:05 AM     T                        




hey     a@mail.com,b@mail.com 80             out                   1/2/2020 1:03:10 AM     T                        
hey     a@mail.com,b@mail.com 80             out                   1/2/2020 1:03:20 AM     T                        

Желаемый вывод

 Start                  End                        Duration          Group
 1/2/2020 1:00:10 AM    1/2/2020 1:00:30 AM        20                A
 1/2/2020 1:02:00 AM    1/2/2020 1:02:05 AM        5                 A
 1/2/2020 1:03:10 AM    1/2/2020 1:03:20 AM        10                A

dput:

 structure(list(Subject = structure(c(1L, 1L, 2L, 2L, 2L, 1L, 
 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c("", "hey"), class = "factor"), 
 Recipient = structure(c(1L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 
 1L, 1L, 2L, 2L), .Label = c("", "sarah@mail.com,gee@mail.com"
 ), class = "factor"), Length = c(80L, 80L, 80L, 80L, 80L, 
 NA, NA, 80L, 80L, NA, NA, 100L, 100L), Folder = structure(c(3L, 
 3L, 3L, 3L, 3L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c("", 
 "draft", "out"), class = "factor"), Message = c(NA, NA, NA, 
 NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Date = structure(c(2L, 
 3L, 4L, 5L, 6L, 1L, 1L, 7L, 8L, 1L, 1L, 9L, 10L), .Label = c("", 
 "1/2/2020 1:00:01 AM", "1/2/2020 1:00:05 AM", "1/2/2020 1:00:10 AM", 
 "1/2/2020 1:00:15 AM", "1/2/2020 1:00:30 AM", "1/2/2020 1:02:00 AM", 
 "1/2/2020 1:02:05 AM", "1/2/2020 1:03:00 AM", "1/2/2020 1:03:20 AM"
 ), class = "factor"), Edit = c(TRUE, TRUE, TRUE, TRUE, TRUE, 
 NA, NA, TRUE, TRUE, NA, NA, TRUE, TRUE)), class = "data.frame", row.names = c(NA, 
-13L))

Я думаю, мне, возможно, придется сделать оператор if / else или какой-то фильтр , Любая помощь / предложение или совет будет принята с благодарностью.

  library(tidyverse)
  library(lubridate)



  df1<-df2 %>%
  mutate(Date = lubridate::mdy_hms(Date), 
  cond = Edit == "T" & ItemFolderName == "out" | Folder == "drafts" &     Message == "" & Subject ==  ?   & Re ==   ?     & Length == ?   , 
     grp = cumsum(!cond)) %>%
  filter(cond) %>%
  group_by(grp) %>%

1 Ответ

1 голос
/ 28 февраля 2020

Решение будет примерно таким. Между предоставленными вами данными и желаемым решением есть некоторые различия, типы столбцов немного отличаются (например, Edit предоставляется в качестве логического). Кроме того, строки немного отличаются, поэтому они не будут соответствовать желаемому результату (вы указываете длину 100 в данных, а не в вашем примере)

Я использовал функцию из этот пост для назначения групповых меток. Он дает число, которое вы можете изменить, чтобы сделать его буквой, если хотите, но вам нужно разобраться с тем, что произойдет, если у вас более 26 групп.

df <- df %>% 
  mutate(Message = ifelse(is.na(Message), '', Message)) %>% 
  mutate(
    cond = Edit & Folder %in% c('out', 'draft') & Message == ''
  ) %>% 
  mutate(grp = cumsum(!cond)) %>% 
  filter(cond, Subject != '')

df$Date <- as.POSIXct(as.character(df$Date), format = '%m/%d/%Y %H:%M:%OS')

get_group_number = function(){
  i = 0
  function(){
    i <<- i+1
    i
  }
}
group_number = get_group_number()
df <- df %>% group_by(Subject, Recipient, Length) %>% mutate(Group = group_number())

df %>% group_by(grp) %>% 
   summarise(Start = min(Date), End = max(Date),
             Duration = End - Start, Group = unique(Group)[1])
# A tibble: 3 x 5
    grp Start               End                 Duration Group
  <int> <dttm>              <dttm>              <drtn>   <dbl>
1     0 2020-01-02 01:00:10 2020-01-02 01:00:30 20 secs      1
2     2 2020-01-02 01:02:00 2020-01-02 01:02:05  5 secs      1
3     4 2020-01-02 01:03:00 2020-01-02 01:03:20 20 secs      2

Я думаю, вы также можете подумать о том, как вы определить группы, так как кажется, что у вас могут быть одни и те же субъект, получатель и длина только случайно

...