#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)