Удалить сложный шаблон из последовательности даты и времени, используя циклы - PullRequest
1 голос
/ 13 апреля 2020

Справочная информация:

У меня есть набор данных, df, где я хотел бы следовать определенному шаблону относительно временных отметок. Я хотел бы сначала

1. Identify the 'Connect' value timestamp
2. Check the action that follows, and check to see if the next action
   is an 'Ended' or 'Attempt' with a less than or equal to 60 second gap
3. If this <= gap of 60 second is present, I wish for the code to Skip these timestamps
   and keep iterating until it comes to the next 'Ended' value, and to record this value.

Шаблон вывода всегда должен следовать за 'Connect' и 'Ended'

We start with:

Connect            4/6/2020 1:11:41 PM

Then look to the next line:

Ended              4/6/2020 1:14:20 PM

Now look to the line that follows:

Attempt            4/6/2020 1:15:20 PM





These two timestamps are less than or equal to 60 seconds, so we keep going    

until we come across an Ended value where these conditions do not apply. 

So the Ended value of 

Ended              4/6/2020 2:05:18 PM    gets recorded.









Action             Time

Connect            4/6/2020 1:11:41 PM

Ended              4/6/2020 1:14:20 PM

Attempt            4/6/2020 1:15:20 PM

Connect            4/6/2020 1:15:21 PM

Ended              4/6/2020 2:05:18 PM

Connect            3/31/2020 11:00:08 AM

Ended              3/31/2020 11:14:54 AM

Ended              3/31/2020 4:17:43 PM

Как мы увидим ниже, эти строки были удалены начиная с 1: 14:20 PM и 13:15:20 PM равны или меньше 60 se c друг от друга, и 31.03.2020 16:17:43 PM не является следующим непосредственным значением 'Ended', с которым мы сталкиваемся.

Ended              4/6/2020 1:14:20 PM

Attempt            4/6/2020 1:15:20 PM

Connect            4/6/2020 1:15:21 PM

Ended              3/31/2020 4:17:43 PM

Требуемый выход:

Action              Time



Connect             4/6/2020 1:11:41 PM        

Ended               4/6/2020 2:05:18 PM

Connect             3/31/2020 11:00:08 AM

Ended               3/31/2020 11:14:54 AM

Выходной шаблон всегда должен следовать за 'Connect' и 'Ended'

Dput:

structure(list(Action = structure(c(2L, 3L, 1L, 2L, 3L, 2L, 3L, 

3L), .Label = c("Attempt", "Connect", "Ended"), class =     "factor"), 

 Time = structure(c(4L, 5L, 6L, 7L, 8L, 1L, 2L, 3L), .Label =      c("3/31/2020 11:00:08 AM", 

 "3/31/2020 11:14:54 AM", "3/31/2020 4:17:43 PM", "4/6/2020      1:11:41 PM", 

  "4/6/2020 1:14:20 PM", "4/6/2020 1:15:20 PM", "4/6/2020  1:15:21   PM", 

 "4/6/2020 2:05:18 PM"), class = "factor")), class =     "data.frame", row.names = c(NA, 

-8L))

Это то, что я пробовал:

Я думаю, что я должен использовать al oop, но не совсем уверен, как построить это. Любая помощь приветствуется.

  library(lubridate)

  if (value <= 60) {

   print("") 

   } else {

   Expr2

   }

Ответы [ 2 ]

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

Мы могли бы преобразовать класс «Время» в класс Datetime с помощью mdy_hms из lubridate, создать группирующую переменную на основе вхождения «Соединить» в «Действие», получить разницу в элементах «Время» ( 'Diff'), filter из строк, где разница меньше или равна 60, затем filter из duplicated аналогичных строк элементов из "Action"

library(dplyr)
library(lubridate)
library(data.table)
df1 %>%
   mutate(Time1 = mdy_hms(Time)) %>%
   group_by(grp = cumsum(Action == 'Connect')) %>% 
   mutate(Diff = difftime(Time1, lag(Time1), unit = 'sec'),
     Diff = case_when(any(Diff <=60) ~ 60, TRUE ~ as.numeric(Diff))) %>%
   filter(Action == 'Connect'|Diff >60) %>%
   ungroup %>% 
   filter(!duplicated(rleid(Action))) %>% 
   select(Action, Time)
# A tibble: 4 x 2
#  Action  Time                    
#  <fct>   <fct>                   
#1 Connect 4/6/2020      1:11:41 PM
#2 Ended   4/6/2020 2:05:18 PM     
#3 Connect 3/31/2020 11:00:08 AM   
#4 Ended   3/31/2020 11:14:54 AM   
2 голосов
/ 13 апреля 2020

Вот подход с dplyr, data.table и lubridate.

Сначала мы рассчитываем совокупное время, прошедшее в наборе данных. Затем мы используем cumsum, чтобы разбить набор данных на попытки соединения, которые находятся на расстоянии более 60 секунд. Затем мы группируем попытки подключения и сохраняем события, не связанные с подключением, только если они происходят более чем через 60 секунд после первой попытки подключения. А затем позаимствовать из подхода @ akrun, отфильтровать повторяющиеся последовательные действия.

library(lubridate)
library(dplyr)
library(data.table)
df %>% 
  mutate(Time = mdy_hms(Time)) %>%
  dplyr::arrange(Time) %>%
  mutate(CumTime = cumsum(time_length(Time - dplyr::lag(Time, 1L,default = as.integer(min(mdy_hms(df$Time))))))) %>%
  group_by(Action) %>%
  mutate(LastConnect = if_else(Action == "Connect", time_length(CumTime - dplyr::lag(CumTime, 1L, 0)), 0)) %>%
  ungroup %>%
  mutate(ConnectionInterval = cumsum(Action == "Connect" & LastConnect > 60)) %>%
  dplyr::select(-LastConnect) %>%
  group_by(ConnectionInterval) %>%
  mutate(ConnectCumTime = time_length(Time - dplyr::lag(Time, 1L))) %>% 
  filter(Action == "Connect" | ConnectCumTime > 60 & !duplicated(rleid(Action)))
## A tibble: 6 x 5
## Groups:   ConnectionInterval [3]
#  Action  Time                CumTime ConnectionInterval ConnectCumTime
#  <fct>   <dttm>                <dbl>              <int>          <dbl>
#1 Connect 2020-03-31 11:00:08       0                  0             NA
#2 Ended   2020-03-31 11:14:54     886                  0            886
#3 Connect 2020-04-06 13:11:41  526293                  1             NA
#4 Ended   2020-04-06 13:14:20  526452                  1            159
#5 Connect 2020-04-06 13:15:21  526513                  2             NA
#6 Ended   2020-04-06 14:05:18  529510                  2           2997
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...