Определить самую последнюю дату перед другой датой из другого столбца для каждой группы с помощью dplyr?

#r #dplyr

#r #dplyr

Вопрос:

У меня есть фрейм данных, структурированный следующим образом:

 example <- data.frame(id = c(1,1,1,2,2,2,3,3,3),
                         delivereddate = c("7/20/2019","7/24/2019","7/28/2019","3/24/2019","4/13/2019","4/25/2019","11/13/2019","11/20/2019","11/27/2019"),
                         applieddate = c("7/22/2019","7/22/2019","7/22/2019",NA,NA,NA,"11/21/2019","11/21/2019","11/21/2019"))
  

Я пытаюсь добавить столбец, который идентифицирует самую последнюю дату доставки перед applieddate для каждого идентификатора. Пример того, что я пытаюсь получить для конечного результата, следующий:

 desiredresult <- data.frame(id = c(1,1,1,2,2,2,3,3,3),
                            delivereddate = c("7/20/2019","7/24/2019","7/28/2019","3/24/2019","4/13/2019","4/25/2019","11/13/2019","11/20/2019","11/27/2019"),
                            applieddate = c("7/22/2019","7/22/2019","7/22/2019",NA,NA,NA,"11/21/2019","11/21/2019","11/21/2019"),
                            applied = c(1,0,0,0,0,0,0,1,0))
  

Мне нужно, чтобы применяемый столбец был двоичным (0 или 1), и для каждого идентификатора может быть только 1 строка с флагом 1. Если идентификатор не имеет applieddate, то применяемый флаг равен 0 для всех строк.

Ответ №1:

Мы могли бы использовать findInterval

 library(dplyr)
library(lubridate)
example %>% 
      dplyr::group_by(id) %>% 
      dplyr::mutate(applied =  (row_number() %in% 
              findInterval(lubridate::mdy(first(applieddate)), 
                          lubridate::mdy(delivereddate))))
# A tibble: 9 x 4
# Groups:   id [3]
#     id delivereddate applieddate applied
#  <dbl> <chr>         <chr>         <int>
#1     1 7/20/2019     7/22/2019         1
#2     1 7/24/2019     7/22/2019         0
#3     1 7/28/2019     7/22/2019         0
#4     2 3/24/2019     <NA>              0
#5     2 4/13/2019     <NA>              0
#6     2 4/25/2019     <NA>              0
#7     3 11/13/2019    11/21/2019        0
#8     3 11/20/2019    11/21/2019        1
#9     3 11/27/2019    11/21/2019        0
  

Ответ №2:

Вы можете преобразовать столбцы в класс date, вычесть applieddate из delivereddate и получить абсолютное значение. Для каждого id мы затем присваиваем 1 индексу, где наблюдается минимальная разница.

 library(dplyr)

example %>%
  mutate(across(ends_with('date'), lubridate::mdy), 
         applied = abs(delivereddate - applieddate)) %>%
  group_by(id) %>%
  mutate(applied =  (row_number() %in% which.min(applied)))

#     id delivereddate applieddate applied
#  <dbl> <date>        <date>        <int>
#1     1 2019-07-20    2019-07-22        1
#2     1 2019-07-24    2019-07-22        0
#3     1 2019-07-28    2019-07-22        0
#4     2 2019-03-24    NA                0
#5     2 2019-04-13    NA                0
#6     2 2019-04-25    NA                0
#7     3 2019-11-13    2019-11-21        0
#8     3 2019-11-20    2019-11-21        1
#9     3 2019-11-27    2019-11-21        0