Объединить значения строк на основе временного интервала

#r #dplyr

#r #dplyr

Вопрос:

У меня есть такой фрейм данных

 node <- c("ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC")
activity <-c("NODE_ISOLATION","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF","NODE_ISOLATION","LOSS_OF_MULTIPLEX_SECTION-OMS_A","NODE_ISOLATION","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF", "UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A","UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A") 

e <-c("2020-05-08 16:11:58","2020-05-08 16:11:58","2020-05-08 16:30:07","2020-05-09 03:00:08","2020-05-09 03:08:08","2020-05-09 03:28:08","2020-05-09 13:08:08","2020-05-09 13:10:08","2020-05-09 13:28:08")

df <- data.frame(node, activity, e)
df
 

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

 node <- c("ABCC","ABCC","ABCC")

activity <-c("NODE_ISOLATION,NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF,NODE_ISOLATION","LOSS_OF_MULTIPLEX_SECTION-OMS_A,NODE_ISOLATION,NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF,UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A,UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A") 

cnt <- c(3,3,3)
df1 <- data.frame(node, activity, cnt)
df1
 

Ответ №1:

Это выглядит как совокупная сумма разностей во времени со сбросом.

Задайте threshold максимальную разницу во времени для группы. В этом случае используйте 30 минут (30 * 60 = 1800 секунд).

Убедитесь e POSIXct , что это так .

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

Итак, подход с использованием этой пользовательской функции таков: во-первых, group_by(node) для оценок, выполненных внутри каждого node . Вычислить различия diff между строками. Определите group не более 30 минут для каждого, используя пользовательскую функцию. Затем, group_by это новое group , подсчитайте строки для каждой группы и используйте toString для ввода activity коллективных значений, разделенных запятыми.

 library(tidyverse)

threshold <- 30 * 60 # 30 minutes * 60 seconds

df$e <- as.POSIXct(df$e)

cumsum_with_reset <- function(x, threshold) {
  cumsum <- 0
  group <- 0
  result <- numeric()
  for (i in seq_along(x)) {
    cumsum <- cumsum   x[i]
    if (cumsum >= threshold) {
      group <- group   1
      cumsum <- 0
    }
    result = c(result, group)
  }
  return (result)
}

df %>%
  group_by(node) %>%
  mutate(diff = c(0, diff(e)),
         group = cumsum_with_reset(diff, threshold)) %>%
  group_by(group, .add = TRUE) %>%
  summarise(cnt = n(),
            activity = toString(activity)) %>%
  dplyr::select(-group)
 

Вывод

   node    cnt activity                                                                                                         
  <chr> <int> <chr>                                                                                                            
1 ABCC      3 NODE_ISOLATION, NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF, NODE_ISOLATION                                              
2 ABCC      3 LOSS_OF_MULTIPLEX_SECTION-OMS_A, NODE_ISOLATION, NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF                             
3 ABCC      3 NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF, UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A, UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A
 

Комментарии:

1. Большое вам спасибо за ваш вклад. Я достиг желаемого результата.

2. У меня есть одна проблема, происходят ли какие-либо два действия в одно и то же время, как это изменить?

3. Не могли бы вы уточнить подробнее? Может быть, обновить свой вопрос с помощью примера? Что бы вы хотели, чтобы произошло, если одновременно выполняются 2 действия?

4. Похоже, что первые две строки вашего примера имеют одинаковое время. Но похоже, что мой вывод совпадает с вашим желаемым фреймом данных df1 . Вы хотели другого результата? Если это так, не стесняйтесь редактировать свой вопрос df1 так, как должен выглядеть ваш окончательный вариант, с примерами данных, которые имеют действия с тем же временем. Я был бы рад вернуться и снова отредактировать ответ.

Ответ №2:

 node <- c("ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC")
activity <-c("NODE_ISOLATION","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF","NODE_ISOLATION","LOSS_OF_MULTIPLEX_SECTION-OMS_A","NODE_ISOLATION","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF", "UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A","UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A") 

e <-c("2020-05-08 16:11:58","2020-05-08 16:11:58","2020-05-08 16:30:07","2020-05-09 03:00:08","2020-05-09 03:08:08","2020-05-09 03:28:08","2020-05-09 13:08:08","2020-05-09 13:10:08","2020-05-09 13:28:08")

df <- data.frame(node, activity, e)

library(dplyr)
##### Change e format 
df <- df %>% mutate(e=as.POSIXct(e))

##### 1st Breaks option automatic 
start <- as.POSIXct("2020-05-08 16:00:00") # Can be min(as.POSIXct(df$e))
end <- max(as.POSIXct(df$e)) 30*60
breaks_a <- seq(start,end,"30 min")

##### 2nd Breaks option manual
breaks_m <- c(as.POSIXct("2020-05-08 16:00:00"),
              as.POSIXct("2020-05-08 16:31:00"),
              as.POSIXct("2020-05-09 03:30:00"),
              as.POSIXct("2020-05-09 13:30:00"))

df <- df %>% mutate(e_cut_automatic=cut(e,breaks_a),
                    e_cut_manual=cut(e,breaks_m))

count_act <- function(x) data.frame(node=x$node[1],
                                    activity=paste(x$activity,collapse=","),
                                    cnt=nrow(x))

count_n <- function(x) do.call("rbind",lapply(split(x,x$node),count_act))


##### With automatic breaks (recomend)
r <- do.call("rbind",lapply(split(df,df$e_cut_automatic),count_n))
print(r,row.names = FALSE)
 

Вывод:
введите описание изображения здесь

 ##### With manual breaks
r <- do.call("rbind",lapply(split(df,df$e_cut_manual),count_n))
print(r,row.names = FALSE)
 

Вывод:
введите описание изображения здесь

Комментарии:

1. Есть ли какие-либо предложения для большого набора данных

2. Конечно, посмотрите мой новый ответ.

Ответ №3:

Попробуйте это:

 node <- c("ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC","ABCC")
activity <-c("NODE_ISOLATION","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF","NODE_ISOLATION","LOSS_OF_MULTIPLEX_SECTION-OMS_A","NODE_ISOLATION","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF","NE_NOT_REACH_VIA_PRIMARY_MNG_INTERF", "UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A","UNDERLYING_RESOURCE_UNAVAILABLE-OMS_A") 
e <-c("2020-05-08 16:11:58","2020-05-08 16:11:58","2020-05-08 16:30:07","2020-05-09 03:00:08","2020-05-09 03:08:08","2020-05-09 03:28:08","2020-05-09 13:08:08","2020-05-09 13:10:08","2020-05-09 13:28:08")

df <- data.frame(node, activity, e)

as.data.table(df) %>% mutate(e_cut=cut(as.POSIXct(e),"30 min")) %>%
  group_by(node, e_cut) %>%
  summarise(activity=paste(activity,collapse=","),cnt = n())%>%
  select(-e_cut)