Как рассчитать конечную дату R на основе следующей начальной даты и преобразовать данные в число дат / временные ряды?

#r #date #time #dplyr #lubridate

#r #Дата #время #dplyr #lubridate

Вопрос:

Новичок здесь снова

Я искал ответ на stackoverflow, но безуспешно

Если вы знаете, есть онлайн-руководства, в которых объясняется, как я должен / мог бы решить эти проблемы, я хотел бы услышать.

ДАННЫЕ

 test <- structure(list(record_id = c(110032, 110032, 110321, 110321, 
110032, 110032, 110032, 110032, 110321), start_fu = structure(c(16302, 
16302, 17308, 17308, 16302, 16302, 16302, 16302, 17308), class = "Date"), 
    end_fu = structure(c(17033, 17033, 17828, 17828, 17033, 17033, 
    17033, 17033, 17828), class = "Date"), start_course = structure(c(16301, 
    16302, 17307, 17308, 16355, 16325, 16344, 16499, 17824), class = "Date"), 
    course = structure(c(0, 1, 3, 3, 5, 3, 0, 3, 0), class = c("haven_labelled", 
    "vctrs_vctr", "double"))), row.names = c(NA, -9L), groups = structure(list(
    record_id = c(110032, 110321), .rows = structure(list(c(1L, 
    2L, 5L, 6L, 7L, 8L), c(3L, 4L, 9L)), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = 1:2, class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))
  

ОБЪЯСНЕНИЕ И ПЕРЕМЕННЫЕ

Итак, я собрал последующие данные из нескольких записей. Теперь я показываю две записи. Во время последующего наблюдения эти люди могут переключаться. Дата начала этого курса была записана.

  • record_id = индивидуальный уникальный идентификатор
  • start_fu = начало выполнения
  • end_fu = конец выполнения
  • start_course = дата начала курса
  • курс = какой курс был начат

ВОПРОС 1

Я хочу создать переменную с именем stop_course . Это вычисляется на основе start_course следующего курса. (start_course — 1 день) Если следующего курса нет, то он должен основываться на дате end_fu.

ОЖИДАЕМЫЙ РЕЗУЛЬТАТ 1

 | record_id | start_fu   | end_fu     | start_course | course | stop_course |
|-----------|------------|------------|--------------|--------|-------------|
|    110032 | 2014-08-20 | 2016-08-20 | 2014-08-19   | 0      | 2014-08-19  |
|    110032 | 2014-08-20 | 2016-08-20 | 2014-08-20   | 1      | 2014-09-11  |
|    110032 | 2014-08-20 | 2016-08-20 | 2014-09-12   | 3      | 2014-09-30  |
|    110032 | 2014-08-20 | 2016-08-20 | 2014-10-01   | 0      | 2014-10-11  |
|    110032 | 2014-08-20 | 2016-08-20 | 2014-10-12   | 5      | 2014-03-04  |
|    110032 | 2014-08-20 | 2016-08-20 | 2015-03-05   | 3      | 2016-08-20  |
|    110321 | 2017-05-22 | 2018-10-24 | 2017-05-21   | 3      | 2017-05-21  |
|    110321 | 2017-05-22 | 2018-10-24 | 2017-05-22   | 3      | 2018-10-19  |
|    110321 | 2017-05-22 | 2018-10-24 | 2018-10-20   | 0      | 2018-10-24  |
  

ВОПРОС 2
В конце я хочу создать для каждого record_id ежедневный список с их курсами.
Таким образом: создайте переменную day_count

ОЖИДАЕМЫЙ РЕЗУЛЬТАТ 2

 | record_id | day_count | date       | course |
|-----------|-----------|------------|--------|
|    110032 | 0         | 2014-08-19 | 0      |
|    110032 | 1         | 2014-08-20 | 1      |
|    110032 | 2         | 2014-08-21 | 1      |
|       ... | ...       | ...        | ...    |
|    110032 | 24        | 2014-09-12 | 3      |
|    110032 | 25        | 2013-09-13 | 3      |
|       ... | ...       | ...        | ...    |
  

Надеюсь, вы сможете помочь мне с кодированием или предоставить мне несколько хороших руководств

BW КБ

Ответ №1:

Использование dplyr и tidyr вот способ :

Мы можем использовать lead , чтобы получить следующую дату start_course и вычесть из нее 1 день со default значением в качестве last значения из end_fu в каждом record_id . Затем мы можем создать последовательность от первой даты до последней даты, fill course значение и создать day_count столбец.

 library(dplyr)
library(tidyr)

test %>%
  group_by(record_id) %>%
  mutate(stop_course = lead(start_course - 1, default = last(end_fu))) %>%
  complete(start_course = seq(min(start_course), max(start_course), 'day')) %>%
  select(-ends_with('fu'), -stop_course) %>%
  fill(course) %>%
  mutate(day_count = row_number() - 1) %>%
  rename(date = start_course) 


#   record_id date          course day_count
#       <dbl> <date>     <dbl lbl>     <dbl>
# 1    110032 2014-08-19         0         0
# 2    110032 2014-08-20         1         1
# 3    110032 2014-08-21         1         2
# 4    110032 2014-08-22         1         3
# 5    110032 2014-08-23         1         4
# 6    110032 2014-08-24         1         5
# 7    110032 2014-08-25         1         6
# 8    110032 2014-08-26         1         7
# 9    110032 2014-08-27         1         8
#10    110032 2014-08-28         1         9
# … with 707 more rows
  

Комментарии:

1. Еще раз спасибо! Это частично работало в большой базе данных. Я частично использовал код для создания ожидаемого результата 1: test %>% group_by(record_id) %>% mutate(stop_course = lead(start_course — 1, default = last(end_fu))) С помощью этого я мог бы создать ожидаемый результат 1. Затем я использовал код целиком, как указано выше, для создания ожидаемого результата 2. Здесь я получил этот код ошибки: ошибка в seq.int (0, to0 — from, by) : ‘to’ должно быть конечным числом. Есть ли у вас какие-либо идеи, откуда это взялось? Возможно, в самих данных? Если

2. Возможно, у вас есть NA значения в данных. Попробуйте добавить na.rm = TRUE min max функции и. Измените complete строку на complete(start_course = seq(min(start_course, na.rm = TRUE), max(start_course, na.rm = TRUE), 'day'))

3. Да, это сработало. Я обнаружил небольшую ошибку в коде: максимальное значение должно быть установлено на stop_course. В противном случае он прекратит подсчет при последнем start_course