Создание столбцов на основе нескольких полусложных условий фильтрации в R (dplyr, stringr, lubridate) - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть набор данных, df

 Read      Box       ID      Time                            
 T         out               10/1/2019 9:00:01 AM
 T         out               10/1/2019 9:00:02 AM             
 T         out               10/1/2019 9:00:03 AM            
 T         out               10/1/2019 9:02:59 AM             
 T         out               10/1/2019 9:03:00 AM
 F                           10/1/2019 9:05:00 AM
 T         out               10/1/2019 9:06:00 AM             
 T         out               10/1/2019 9:06:02 AM             
 T         in                10/1/2019 9:07:00 AM
 T         in                10/1/2019 9:07:02 AM
 T         out               10/1/2019 9:07:04 AM
 T         out               10/1/2019 9:07:05 AM             
 T         out               10/1/2019 9:07:06 AM             
 T         out    hello      10/1/2019 9:07:08 AM
 F         in                10/1/2019 9:08:10 AM
 F         in                10/1/2019 9:08:11 AM
 T         draft             10/2/2019 10:00:00 AM
 T         draft             10/2/2019 10:00:05 AM
 T         draft             10/2/2019 10:00:20 AM
 T         draft             10/2/2019 10:00:25 AM
 T         draft             10/2/2019 10:02:00 AM
 T         draft             10/2/2019 10:02:20 AM

На основании определенных условий в этом наборе данных я хотел бы создать столбец времени начала и столбца времени окончания.

Я хотел бы создать время начала, когда происходит следующее: чтение == "T", Box == "out" ИЛИ Box == "draft" и ID == ""

Я хотел бы создать "endtime «когда происходит следующее: Read ==« T », Box ==« out »ИЛИ Box ==« черновик »и ID ==« »и когда разрыв между требуемыми условиями составляет менее 30 секунд.

Когда возникает первый случай этого условия, генерируется время запуска. Например, для этого набора данных начальное время будет 01.10.2009 9:00:01, поскольку именно здесь мы видим желаемые условия: Read = T, Box = "out" или Box == "draft" и ID = " "

Однако в тот момент, когда любое из этих условий не выполняется, ИЛИ, если время между метками времени превышает 30 секунд, будет создано конечное время. Так, например, начальное время создается в строке 17 по адресу: 02.10.2009 10:00:00, а конечное время будет создано в строке 20 по адресу: 02.10.2009 10:00:25

Следующее время запуска будет создано в: 10/2/2019 10:02:00 AM, поскольку время между метками времени превышает 30 секунд. Я не уверен, что мне нужно включить THRE sh в этот код, чтобы удовлетворить это? Я просто не уверен, как это реализовать. Любые предложения приветствуются.

  starttime                    endtime                     duration

  10/1/2019 9:00:01 AM        10/1/2019 9:03:00 AM         179 secs
  10/1/2019 9:06:00 AM        10/1/2019 9:06:02 AM         2 secs
  10/1/2019 9:07:05 AM        10/1/2019 9:07:06 AM         1 secs
  10/2/2019 10:00:00 AM       10/2/2019 10:00:25 AM        25 secs
  10/2/2019 10:02:00 AM       10/2/2019 10:02:20 AM        20 secs

dput:

  structure(list(Read = c(TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, 
  TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, 
  TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), Box = structure(c(4L, 4L, 
  4L, 4L, 4L, 1L, 4L, 4L, 3L, 3L, 4L, 4L, 4L, 4L, 3L, 3L, 2L, 2L, 
  2L, 2L, 2L, 2L), .Label = c("", "draft", "in", "out"), class = "factor"), 
  ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
  1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("", 
  "hello"), class = "factor"), Time = structure(1:22, .Label = c("10/1/2019 9:00:01 AM", 
  "10/1/2019 9:00:02 AM", "10/1/2019 9:00:03 AM", "10/1/2019 9:02:59 AM", 
  "10/1/2019 9:03:00 AM", "10/1/2019 9:05:00 AM", "10/1/2019 9:06:00 AM", 
  "10/1/2019 9:06:02 AM", "10/1/2019 9:07:00 AM", "10/1/2019 9:07:02 AM", 
  "10/1/2019 9:07:04 AM", "10/1/2019 9:07:05 AM", "10/1/2019 9:07:06 AM", 
  "10/1/2019 9:07:08 AM", "10/1/2019 9:08:10 AM", "10/1/2019 9:08:11 AM", 
  "10/2/2019 10:00:00 AM", "10/2/2019 10:00:05 AM", "10/2/2019 10:00:20 AM", 
  "10/2/2019 10:00:25 AM", "10/2/2019 10:02:00 AM", "10/2/2019 10:02:20 AM"
   ), class = "factor")), class = "data.frame", row.names = c(NA, 
  -22L))

Я хотел бы также включить Box == "draft", а также> 30-секундную строку sh в пределах этот код

  library(dplyr)



  Thresh <- 30  (seconds)


  df1<-df %>%
  mutate(Time = lubridate::mdy_hms(Time), 
     cond = Read == "True" & Box == "out"|Box == "draft" & ID == "" , 
     grp = cumsum(!cond)) %>%
  filter(cond) %>%
  group_by(grp) %>%
  summarise(starttime = first(Time), 
        endtime = last(Time), 
        duration = difftime(endtime, starttime, units = "secs")) %>%
  select(-grp)

1 Ответ

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

Кажется, есть несогласованность в том, как правила применяются в примере, приведенном в вопросе. Неясно, должно ли это пройти 30 секунд с момента последней отметки времени как начало нового или конец предыдущего периода. Оба примера используются в примере.

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

Этот метод работает без циклов. Он разбивает время на последовательные прогоны «действительного» времени (т.е. те, которые соответствуют критериям), а затем разбивает их, если есть промежутки более 30 секунд. Затем он просто извлекает минимальное и максимальное время в каждой подгруппе.

library(lubridate)

df$Time <- dmy_hms(df$Time)
valid   <- df$Read == TRUE & df$ID == "" & (df$Box == "out" | df$Box == "draft")
groups  <- rep(seq_along(rle(valid)$lengths), rle(valid)$lengths)
dflist  <- lapply(split(df[valid, ], groups[valid]), function(x) {
                    y <- as.numeric(difftime(x$Time, lag(x$Time)))
                    split(x, cumsum(is.na(y) | y > 30))
                  })

start   <- lapply(dflist, function(x) lapply(x, function(y) as.character(min(y$Time))))
end     <- lapply(dflist, function(x) lapply(x, function(y) as.character(max(y$Time))))
start   <- as.POSIXct(unlist(start))
end     <- as.POSIXct(unlist(end))

data.frame(start = start, end = end, duration = difftime(end, start))
#>                   start                 end duration
#> 1.0 2019-01-10 09:00:01 2019-01-10 09:03:00 179 secs
#> 3.0 2019-01-10 09:06:00 2019-01-10 09:06:02   2 secs
#> 5.0 2019-01-10 09:07:04 2019-01-10 09:07:06   2 secs
#> 7.0 2019-02-10 10:00:00 2019-02-10 10:02:20 140 secs

Создано в 2020-02-20 пакетом Представить (v0.3.0)

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