【问题标题】:Count calendar days within a date interval using lubridate使用 lubridate 计算日期间隔内的日历天数
【发布时间】:2020-07-01 06:49:15
【问题描述】:

我有入院和出院天数的数据集,我想从中生成三年期间每个日历日的占用床位数。我正在使用 tidyverse 和 lubridate 软件包。

到目前为止,我的方法是将录取/出院列转换为间隔(数据很敏感,因此我无法分享实际日期):

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

然后创建一个小标题,其中每一行对应于时间范围,加上一列可以在 for 循环中添加的零:

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

不幸的是,我不知道如何创建一个 for 循环来计算每个间隔内的天数。到目前为止,这是我的尝试,它给了我 24 的统一值:

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

【问题讨论】:

    标签: r date lubridate


    【解决方案1】:

    样本数据。

    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
    

    【讨论】:

    • 太完美了。感谢您提供快速响应和示例代码来制作示例数据。
    • 我应该注意,这不一定包含序列中的所有日期......虽然不太可能,但如果日期的占用率为零,那么它将不会出现在最后一帧中。这可以通过保存原始Map(...) 结果并将该数据重新加入到整体结果中来解决(使用count=0)。但同样,也许不太可能。
    • 感谢您的来信。出于我的目的,这应该没问题,因为我是按月汇总的,所以缺少一两天并不重要,并且有 1600 个患者病例,所以应该有足够的覆盖范围。
    【解决方案2】:

    这是使用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)
    

    我们在admitdischargecount 之间创建一个日期序列,每个唯一日期都将其与t 连接起来,以便t 中的所有日期保持不变。

    【讨论】:

    • 太棒了。这也很有效,我喜欢它在 tidyverse 中的效果!
    猜你喜欢
    • 1970-01-01
    • 2012-03-26
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 2016-09-08
    相关资源
    最近更新 更多