计算每年两个日期之间的天数

count the number of days between two dates per year

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

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 可能有帮助,但我不确定在哪里开始。

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

这是一个基本的 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