Вы можете попробовать:
library(dplyr)
df <- df %>%
arrange(id, work_start, work_end) %>%
group_by(id) %>%
mutate(cumMaxDate = setattr(cummax(unclass(work_end)), "class", "Date")) %>%
group_by(id, idx = cumsum(+(work_start > (lag(cumMaxDate, default = first(cumMaxDate)) + 1)))) %>%
summarise(work_start = min(work_start), work_end = max(cumMaxDate), duration = difftime(work_end, work_start)) %>%
ungroup() %>% select(-idx)
Вывод:
# A tibble: 1 x 4
id work_start work_end duration
<fct> <date> <date> <drtn>
1 Joe 2004-06-23 2019-03-31 5394 days
Обратите внимание, что если бы у Джо было два непоследовательных периода, то вам потребуется group_by(id)
снова после последнего ungroup
и просто сделайте mutate(duration = sum(duration)
или подобное.
С другой стороны, если вы много работаете с данными такого типа (например, полученными в системах CRM или HCM), вы можете взглянуть на моя посылка neatRanges
. Вышеупомянутая проблема может быть решена следующим образом:
# install.packages('neatRanges')
library(dplyr) # Just for the purpose of using the pipes and `mutate`
df %>%
neatRanges::collapse_ranges(., groups = 'id', start_var = 'work_start', end_var = 'work_end') %>%
mutate(duration = difftime(work_end, work_start))
Вывод:
id work_start work_end duration
1 Joe 2004-06-23 2019-03-31 5394 days
Обратите внимание, что пакет все еще находится на ранних этапах, однако по крайней мере функция collapse_ranges
была До некоторой степени проверено в бою - с другой стороны, если у вас есть предложения по улучшению или вы найдете какие-либо ошибки, о которых вы можете сообщить на GitHub .