如何基于起止日期补全不重叠的缺失日期范围(R语言)
补全不重叠的日期范围(基于指定上下限)
需要基于给定的起始边界(2000-01-01)和结束边界(2001-07-31)补全现有数据集中的缺失日期区间,且所有最终的日期区间必须互不重叠。
现有数据集
have <- data.frame(ID = c(1, 1), date1 = as.Date(c("2000-01-29", "2000-07-16")), date2 = as.Date(c("2000-07-15", "2001-04-30"))) # 输出 # ID date1 date2 # 1 1 2000-01-29 2000-07-15 # 2 1 2000-07-16 2001-04-30
期望结果
want <- data.frame(ID = c(1, 1, 1, 1), date1 = as.Date(c("2000-01-01", "2000-01-29", "2000-07-16", "2001-05-01")), date2 = as.Date(c("2000-01-28", "2000-07-15", "2001-04-30", "2001-07-31"))) # 输出 # ID date1 date2 # 1 1 2000-01-01 2000-01-28 # 2 1 2000-01-29 2000-07-15 # 3 1 2000-07-16 2001-04-30 # 4 1 2001-05-01 2001-07-31
原方案的问题
原方案生成的区间存在日期重叠(如2000-07-15同时作为前一个区间的date2和后一个补全区间的date1),导致区间边界重复:
library(dplyr) start <- as.Date("2000-01-01"); end <- as.Date("2001-07-31") ex <- have %>% group_by(ID) %>% summarize(newdate1 = c(start, date2), newdate2 = c(date1, end)) %>% rename(date1 = newdate1, date2 = newdate2) %>% filter(date2 > date1) %>% ungroup() %>% bind_rows(have) %>% arrange(ID, date1) # 输出 # # A tibble: 5 × 3 # ID date1 date2 # <dbl> <date> <date> # 1 1 2000-01-01 2000-01-29 # 2 1 2000-01-29 2000-07-15 # 3 1 2000-07-15 2000-07-16 # 4 1 2000-07-16 2001-04-30 # 5 1 2001-04-30 2001-07-31
修正方案
核心是调整补全区间的边界,避免与原有区间重叠:
- 补全现有区间之前的缺失部分时,将现有区间的
date1减1天作为补全区间的date2 - 补全现有区间之间/之后的缺失部分时,将前一个区间的
date2加1天作为补全区间的date1
修正后的代码:
library(dplyr) start <- as.Date("2000-01-01"); end <- as.Date("2001-07-31") corrected <- have %>% group_by(ID) %>% # 生成补全区间:调整边界避免重叠 summarize( newdate1 = c(start, date2 + 1), newdate2 = c(date1 - 1, end) ) %>% rename(date1 = newdate1, date2 = newdate2) %>% # 过滤无效区间(日期顺序颠倒的情况) filter(date2 >= date1) %>% # 合并原数据并按日期排序 bind_rows(have) %>% arrange(ID, date1) %>% ungroup() # 查看结果 corrected # 输出 # # A tibble: 4 × 3 # ID date1 date2 # <dbl> <date> <date> # 1 1 2000-01-01 2000-01-28 # 2 1 2000-01-29 2000-07-15 # 3 1 2000-07-16 2001-04-30 # 4 1 2001-05-01 2001-07-31
这个结果完全匹配期望的want数据集,所有区间边界互不重叠,且完整覆盖了从start到end的整个时间范围。
内容的提问来源于stack exchange,提问作者TJ87
相关产品推荐
相关产品推荐

