Подсчет календарных дней в интервале дат с использованием lubridate - PullRequest
2 голосов
/ 20 марта 2020

У меня есть набор данных о днях госпитализации и выписки, из которых я хочу рассчитать количество занятых коек для каждого календарного дня периода в три года. Я использую пакеты tidyverse и lubridate.

Мой подход до сих пор заключался в том, чтобы преобразовать столбцы разрешения / выгрузки в интервал (данные чувствительны, поэтому я не могу поделиться фактическими датами):

d <- d %>%
  mutate(duration = admit %--% discharge)

, а затем создать столбец, где каждая строка соответствует временному диапазону, плюс столбец нулей, который может быть добавлен в a для l oop:

t <- 
  tibble(
    days = as.Date(date("2017-01-01"):date("2019-12-31")), 
    count = 0
  )

К сожалению, я не могу понять, как создать для l oop это будет сумма дней, которые попадают в каждый интервал. Вот моя попытка, которая пока дает мне одинаковые значения 24:

for(i in timeline$days) {
  if (i %within% d$duration)
    timeline$count = timeline$count + 1
}

Ответы [ 2 ]

3 голосов
/ 20 марта 2020

Пример данных.

library(dplyr)
set.seed(42)
d <- tibble(admit = Sys.Date() - sample(300, size = 1000, replace = TRUE)) %>%
  mutate(discharge = admit + sample(0:30, size = 1000, replace = TRUE))
d
# # A tibble: 1,000 x 2
#    admit      discharge 
#    <date>     <date>    
#  1 2019-06-18 2019-07-14
#  2 2019-06-11 2019-06-12
#  3 2019-12-24 2020-01-18
#  4 2019-07-13 2019-07-29
#  5 2019-09-08 2019-09-23
#  6 2019-10-15 2019-10-15
#  7 2019-08-11 2019-08-28
#  8 2020-02-07 2020-02-29
#  9 2019-09-03 2019-09-10
# 10 2019-08-20 2019-09-14
# # ... with 990 more rows

Мы можем создать список диапазонов / последовательностей дат с помощью Map (или purrr::pmap):

Map(seq.Date, d$admit, d$discharge, list(by = "days"))[1:2]
# [[1]]
#  [1] "2019-06-18" "2019-06-19" "2019-06-20" "2019-06-21" "2019-06-22" "2019-06-23" "2019-06-24"
#  [8] "2019-06-25" "2019-06-26" "2019-06-27" "2019-06-28" "2019-06-29" "2019-06-30" "2019-07-01"
# [15] "2019-07-02" "2019-07-03" "2019-07-04" "2019-07-05" "2019-07-06" "2019-07-07" "2019-07-08"
# [22] "2019-07-09" "2019-07-10" "2019-07-11" "2019-07-12" "2019-07-13" "2019-07-14"
# [[2]]
# [1] "2019-06-11" "2019-06-12"

и затем объединить их, табулируйте их (с table) и enframe их:

Map(seq.Date, d$admit, d$discharge, list(by = "days")) %>%
  do.call(c, .) %>%
  table() %>%
  tibble::enframe(name = "date", value = "count") %>%
  # because `table` preserves a *character* representation of the Date
  mutate(date = as.Date(date)) %>%
  arrange(date)
# # A tibble: 328 x 2
#    date       count  
#    <date>     <table>
#  1 2019-05-24  1     
#  2 2019-05-25  3     
#  3 2019-05-26  7     
#  4 2019-05-27  8     
#  5 2019-05-28  9     
#  6 2019-05-29 14     
#  7 2019-05-30 20     
#  8 2019-05-31 20     
#  9 2019-06-01 20     
# 10 2019-06-02 21     
# # ... with 318 more rows
2 голосов
/ 20 марта 2020

Вот еще один метод, использующий функции tidyverse.

library(tidyverse)

d %>%
  mutate(days = map2(admit, discharge, seq, by = "day")) %>%
  unnest(days) %>%
  count(days) %>%
  right_join(t, by = "days") %>%
  mutate(n = coalesce(n, as.integer(count))) %>%
  select(-count)

Мы создаем последовательность дат между admit и discharge, count каждой уникальной датой, соединяем ее с t, чтобы все даты в t оставались неизменными.

...