Я бы использовал tidyr::fill
(задокументировано здесь ), чтобы заполнить значения NA TrtDate вперед в вашем data.frame. Это позволит вам эффективно «пропустить» значения NA при расчете интересующих вас количеств в вашем data.frame. Я хотел бы выполнить этот тип действия с копией исходного поля данных, чтобы вы могли визуально проверить логи c и восстановить значения NA
, если это необходимо.
Некоторый код для этого (плюс некоторая часть вашей очистки / нормализации данных):
df1 %>%
# convert to dates
dplyr::mutate(TrtDate = lubridate::ymd(dplyr::na_if(TrtDate, "NA")),
MtDate = lubridate::ymd(dplyr::na_if(MtDate, "NA"))) %>%
dplyr::group_by(ID) %>%
# sort by MtDate
dplyr::arrange(MtDate) %>%
# create a copy of TrtDate which we will use for filling
dplyr::mutate(FillTrtDate = TrtDate) %>%
# fill forward
tidyr::fill(FillTrtDate, .direction = 'down') %>%
# compute difference
dplyr::mutate(PrevTrtDate = lag(FillTrtDate, default = first(TrtDate), order_by = MtDate),
DaysSincePrevTreat = MtDate - PrevTrtDate) %>%
dplyr::ungroup()
Результат:
# A tibble: 12 x 6
ID MtDate TrtDate FillTrtDate PrevTrtDate DaysSincePrevTreat
<fct> <date> <date> <date> <date> <drtn>
1 82002 2019-07-17 2019-07-17 2019-07-17 2019-07-17 0 days
2 82002 2019-07-17 NA 2019-07-17 2019-07-17 0 days
3 82002 2019-07-18 2019-07-21 2019-07-21 2019-07-17 1 days
4 82002 2019-07-18 NA 2019-07-21 2019-07-21 -3 days
5 82002 2019-07-18 NA 2019-07-21 2019-07-21 -3 days
6 82002 2019-07-19 NA 2019-07-21 2019-07-21 -2 days
7 82002 2019-07-19 NA 2019-07-21 2019-07-21 -2 days
8 82002 2019-07-19 NA 2019-07-21 2019-07-21 -2 days
9 82002 2019-07-21 NA 2019-07-21 2019-07-21 0 days
10 82002 2019-07-21 NA 2019-07-21 2019-07-21 0 days
11 82002 2019-07-22 NA 2019-07-21 2019-07-21 1 days
12 82002 2019-07-23 2019-07-23 2019-07-23 2019-07-21 2 days
Что эта структура проясняет, так это то, что Есть некоторые несоответствия в ваших исходных данных примера и желаемого результата. Но это те проблемы, которые приведенные выше инструменты должны помочь вам решить.
edit: подробности о "несоответствиях"
Предоставленный фрейм данных был:
> df1
ID MtDate TrtDate
1 82002 2019-07-17 2019-07-17
2 82002 2019-07-17 NA
3 82002 2019-07-18 2019-07-21
4 82002 2019-07-18 NA
5 82002 2019-07-18 NA
6 82002 2019-07-19 NA
7 82002 2019-07-19 NA
8 82002 2019-07-19 NA
9 82002 2019-07-21 NA
10 82002 2019-07-21 NA
11 82002 2019-07-22 NA
12 82002 2019-07-23 2019-07-23
По вашему желаемому выводу, опечатка есть на 3-й запись. Исправляя это, получим:
df2 <- data.frame(ID = c("82002","82002","82002","82002","82002","82002","82002",
"82002","82002","82002","82002","82002"),
MtDate = c("2019-07-17","2019-07-17","2019-07-18","2019-07-18","2019-07-18",
"2019-07-19","2019-07-19","2019-07-19","2019-07-21",
"2019-07-21","2019-07-22","2019-07-23"),
TrtDate = c("2019-07-17","NA","2019-07-18", "NA", "NA",
"NA", "NA", "NA", "NA","NA", "NA", "2019-07-23"))
или
> df2
ID MtDate TrtDate
1 82002 2019-07-17 2019-07-17
2 82002 2019-07-17 NA
3 82002 2019-07-18 2019-07-18
4 82002 2019-07-18 NA
5 82002 2019-07-18 NA
6 82002 2019-07-19 NA
7 82002 2019-07-19 NA
8 82002 2019-07-19 NA
9 82002 2019-07-21 NA
10 82002 2019-07-21 NA
11 82002 2019-07-22 NA
12 82002 2019-07-23 2019-07-23
Чтобы получить желаемый результат, я бы заполнил вперед, как указано выше, но пропустил шаг lag
:
df2 %>%
# convert to dates
dplyr::mutate(TrtDate = lubridate::ymd(dplyr::na_if(TrtDate, "NA")),
MtDate = lubridate::ymd(dplyr::na_if(MtDate, "NA"))) %>%
dplyr::group_by(ID) %>%
# sort by MtDate
dplyr::arrange(MtDate) %>%
# create a copy of TrtDate which we will use for filling
dplyr::mutate(FillTrtDate = TrtDate) %>%
# fill forward
tidyr::fill(FillTrtDate, .direction = 'down') %>%
# compute difference, while converting to dates
dplyr::mutate(DaysSincePrevTreat = MtDate - FillTrtDate) %>%
dplyr::ungroup()
или
# A tibble: 12 x 5
ID MtDate TrtDate FillTrtDate DaysSincePrevTreat
<fct> <date> <date> <date> <drtn>
1 82002 2019-07-17 2019-07-17 2019-07-17 0 days
2 82002 2019-07-17 NA 2019-07-17 0 days
3 82002 2019-07-18 2019-07-18 2019-07-18 0 days
4 82002 2019-07-18 NA 2019-07-18 0 days
5 82002 2019-07-18 NA 2019-07-18 0 days
6 82002 2019-07-19 NA 2019-07-18 1 days
7 82002 2019-07-19 NA 2019-07-18 1 days
8 82002 2019-07-19 NA 2019-07-18 1 days
9 82002 2019-07-21 NA 2019-07-18 3 days
10 82002 2019-07-21 NA 2019-07-18 3 days
11 82002 2019-07-22 NA 2019-07-18 4 days
12 82002 2019-07-23 2019-07-23 2019-07-23 0 days
Затем вы можете select(-FillTrtDate)
удалить этот вспомогательный столбец, если хотите.