【问题标题】:count the number of days between two dates per year计算每年两个日期之间的天数
【发布时间】:2021-07-08 14:51:44
【问题描述】:

我有一个数据框,每行都有一个开始和结束日期。我想计算两个日期之间的天数并按年份拆分。 所以从这里开始:

id <- c(1,2,3)
start <- as.Date(c('01/01/2015','01/01/2016','07/01/2015'), format = '%m/%d/%Y')
end <- as.Date(c('12/31/2016','12/31/2016','12/31/2016'), format = '%m/%d/%Y')
df <- data.frame(id, start, end)
id Start End
1 01/01/2015 12/31/2016
2 01/01/2016 12/31/2016
3 01/07/2015 12/31/2016

到这里:

id Start End days_no. year_2015 year_2016
1 01/01/2015 12/31/2016 730 365 365
2 01/01/2016 12/31/2016 365 0 365
3 07/01/2015 12/31/2016 548 183 365

感谢任何帮助,请注意我想动态计算年度统计数据,在我的实际案例中我可能会得到很多年的列...我猜 lubridate 可能会有所帮助,但我不确定从哪里开始.

【问题讨论】:

    标签: r date lubridate


    【解决方案1】:

    这是一个基本的 R 选项

    transform(
      df,
      days_no = end - start,
      year_2015 = pmax(as.Date("2015-12-31") - start, 0),
      year_2016 = pmax(end - as.Date("2016-1-1"), 0)
    )
    

    给了

      id      start        end  days_no year_2015 year_2016
    1  1 2015-01-01 2016-12-31 730 days  364 days  365 days
    2  2 2016-01-01 2016-12-31 365 days    0 days  365 days
    3  3 2015-07-01 2016-12-31 549 days  183 days  365 days
    

    【讨论】:

      【解决方案2】:

      这是使用tidyverselubridate 的一种方法。

      首先,按日历年分隔行,用于衡量每年的天数。每行将包括每个日历年要计算的日期,从 1 月 1 日开始,如果重叠多年,则到 12 月 31 日结束。然后,很容易计算给定年份的天数。

      此示例的结果与我的结果略有不同。 2016 年是闰年,有 366 天。如果天数不包括开始日期或结束日期,您会得到不同的答案。

      library(tidyverse)
      library(lubridate)
      
      df %>%
        mutate(date_int = interval(start, end),
               year = map2(year(start), year(end), seq)) %>%
        unnest(year) %>%
        mutate(year_int = interval(as.Date(paste0(year, '-01-01')), as.Date(paste0(year, '-12-31'))),
               year_sect = intersect(date_int, year_int),
               start_new = as.Date(int_start(year_sect)),
               end_new = as.Date(int_end(year_sect))) %>%
        select(id, start_new, end_new) %>%
        mutate(year = year(start_new),
               days = as.numeric(end_new - start_new)) %>%
        right_join(df) %>%
        pivot_wider(id_cols = c(id, start, end), names_from = year, values_from = days, names_prefix = "year_", values_fill = list(days = 0)) %>%
        mutate(days_number = reduce(select(., starts_with("year_")), `+`))
      

      输出

           id start      end        year_2015 year_2016 days_number
        <dbl> <date>     <date>         <dbl>     <dbl>       <dbl>
      1     1 2015-01-01 2016-12-31       364       365         729
      2     2 2016-01-01 2016-12-31         0       365         365
      3     3 2015-07-01 2016-12-31       183       365         548
      

      【讨论】:

      • 这很好用。非常感谢!我不得不对列进行重新排序,但这很棒......它也不需要安装 purr 吗?
      • 很高兴听到!是的 - reducemap2 使用 purrr 但我认为这是加载了 tidyverse...
      • 它加载了 tidyverse,绝对是,我的错……那么一切都好!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-28
      • 2019-04-12
      • 1970-01-01
      • 2017-01-13
      • 2023-03-29
      相关资源
      最近更新 更多