Свернуть в зависимости от состояния
Этот вопрос похож на вопрос, уже опубликованный несколько дней назад, Свернуть строки от 0 до 0
Новый поворот здесь, который отличается от предыдущего вопроса, заключается в следующем: как мы свернем строки по Id только для тех строк, где разное время меньше или равно 60.
Например, используя тот же набор данных
Incident.ID.. date product
INCFI0000029582 2014-09-25 08:39:45 foo
INCFI0000029582 2014-09-25 08:39:45 foo
INCFI0000029582 2014-09-25 08:39:48 bar
INCFI0000029582 2014-09-25 08:40:44 foo
INCFI0000029582 2014-10-10 23:04:00 foo
INCFI0000029587 2014-09-25 08:33:32 bar
INCFI0000029587 2014-09-25 08:34:41 bar
INCFI0000029587 2014-09-25 08:35:24 bar
INCFI0000029587 2014-10-10 23:04:00 foo
df <- structure(list(Incident.ID.. = c("INCFI0000029582", "INCFI0000029582","INCFI0000029582",
"INCFI0000029582", "INCFI0000029582", "INCFI0000029587", "INCFI0000029587",
"INCFI0000029587", "INCFI0000029587"), date = c("2014-09-25 08:39:45","2014-09-25 08:39:45",
"2014-09-25 08:39:48", "2014-09-25 08:40:44", "2014-10-10 23:04:00",
"2014-09-25 08:33:32", "2014-09-25 08:34:41", "2014-09-25 08:35:24",
"2014-10-10 23:04:00"), product =
c("foo","foo","bar","foo","foo","bar","bar","bar","foo")),
class = "data.frame", row.names = c(NA,
-L))
Это вычисляет разницу во времени по ID
library(dplyr)
library(lubridate)
df1 <- df %>%
group_by(Incident.ID..) %>%
arrange(ymd_hms(date)) %>%
mutate(diff = c(0, diff(ymd_hms(date))))
Что приводит к этому новому столбцу diff, как показано ниже
Incident.ID.. date product diff
INCFI0000029582 2014-09-25 08:39:45 foo 0
INCFI0000029582 2014-09-25 08:39:45 foo 0
INCFI0000029582 2014-09-25 08:39:48 bar 3
INCFI0000029582 2014-09-25 08:40:44 foo 56
INCFI0000029582 2014-10-10 23:04:00 foo 1347796
INCFI0000029587 2014-09-25 08:33:32 bar 0
INCFI0000029587 2014-09-25 08:34:41 bar 69
INCFI0000029587 2014-09-25 08:35:24 bar 43
INCFI0000029587 2014-10-10 23:04:00 foo 1348116
Теперь только сворачивающиеся строки Incident.ID..
где разница во времени меньше или равна 60, т.е. diff <= 60
должен привести к окончательному набору данных, как это
Incident.ID.. DateMin DateMax product diff_collapse
INCFI0000029582 2014-09-25 08:39:45 2014-09-25 08:40:44 foo,bar,foo 0,0,3,56
INCFI0000029582 2014-09-25 08:40:44 2014-10-10 23:04:00 foo 1347796
INCFI0000029587 2014-09-25 08:33:32 2014-09-25 08:34:41 bar 0
INCFI0000029587 2014-09-25 08:34:41 2014-09-25 08:35:24 bar,bar 69,43
INCFI0000029587 2014-09-25 08:35:24 2014-10-10 23:04:00 foo 1348116
Нужна помощь в создании такого свернутого набора данных. Заранее спасибо.
2 ответа
Вам нужен столбец группировки, который соответствует вашим потребностям:
... %>% mutate(
grp = ifelse(diff <= 60,
paste0(Incident.ID.., "origin"),
paste0(Incident.ID.., diff)
))
Это создает одинаковый группер (в пределах Incident.ID..
) для строк, где разница меньше 60, и является уникальной в противном случае. (Подразумевается diff
уникален --- если вы могли иметь дублирующиеся различия больше 60, используйте row_number()
вместо diff
в paste
чтобы убедиться, что он уникален.) Используйте его в качестве столбца группировки для кода свертывания.
Я бы предложил создать новую переменную группировки. Я получил желаемый результат примерно так:
df1 <- df %>%
group_by(Incident.ID..) %>%
arrange(ymd_hms(date)) %>%
mutate(diff = c(0, diff(ymd_hms(date)))) %>%
ungroup() %>%
arrange(Incident.ID.., date) %>%
mutate(group = cumsum(diff > 60 | diff == 0)) %>%
group_by(group) %>%
summarise(DateMin = min(date),
DateMax = max(date),
diff_collapse = toString(diff),
product = toString(product))
Я в основном решаю, с какой строки новая группа должна начинаться через условие diff > 60 | diff == 0
: diff > 60
потому что это условие краха, и diff == 0
потому что тогда начинается новый инцидент. Вы могли бы также написать Incident.ID.. != lag(Incident.ID..)
, Заворачивая это в cumsum
увеличивает счетчик каждый раз, когда начинается новая группа.
Важно ungroup
во-первых, в противном случае cumsum
работает только в группе.