我有一个数据集,其中包括一系列日期,需要在新行中填写缺失的日期。df1
是我正在处理的数据的一个例子,df2
是我成功实现的一个例子(我被困在哪里)。df3
是我想结束的地方!
df1
ID Date DateStart DateEnd
1 2/11/2021 2/11/2021 2/17/2021
1 2/19/2021 2/19/2021 2/21/2021
2 1/15/2021 1/15/2021 1/20/2021
2 1/22/2021 1/22/2021 1/23/2021
这就是我对这个的看法。NAs不是问题,因为我打算在完成需要做的事情后删除DateStart和DateEnd列。这里的问题是,我不想包含在之前的DateStart和DateEnd范围内的日期。为了到达这里,我按ID分组并填写df1
中日期之间的缺失日期:
df2
ID Date DateStart DateEnd
1 2/11/2021 2/11/2021 2/17/2021
1 2/12/2021 NA NA
1 2/13/2021 NA NA
1 2/14/2021 NA NA
1 2/15/2021 NA NA
1 2/16/2021 NA NA
1 2/17/2021 NA NA
1 2/18/2021 NA NA
1 2/19/2021 2/19/2021 2/21/2021
2 1/15/2021 1/15/2021 1/20/2021
2 1/16/2021 NA NA
2 1/17/2021 NA NA
2 1/18/2021 NA NA
2 1/19/2021 NA NA
2 1/20/2021 NA NA
2 1/21/2021 NA NA
2 1/22/2021 NA NA
2 1/23/2021 1/23/2021 1/24/2021
这实际上是我想结束的:
df3
ID Date DateStart DateEnd
1 2/11/2021 2/11/2021 2/17/2021
1 2/18/2021 NA NA
1 2/19/2021 2/19/2021 2/21/2021
2 1/15/2021 1/15/2021 1/20/2021
2 1/21/2021 NA NA
2 1/22/2021 NA NA
2 1/23/2021 1/23/2021 1/24/2021
在df3
中,缺失的日期被填充,但不包含dateststart - dateend范围内的日期。
对如何实现这一点有什么想法吗?注:我有一个包含大量观测值的数据集。
-
将日期列转换为日期类。
-
对于每个
ID
,使用complete
创建从DateStart
的最小值到DateEnd
的最大值的日期序列。 -
fill
的NA
值与以前的非na,Date > DateEnd
除外。 -
对于
ID
、DateStart
和DateEnd
的每一组,保留NA
值或行号为1的行。
library(dplyr)
library(tidyr)
df %>%
mutate(across(-ID, lubridate::mdy)) %>%
group_by(ID) %>%
complete(Date = seq(min(DateStart), max(DateEnd), by = '1 day')) %>%
fill(DateStart, DateEnd) %>%
ungroup %>%
mutate(across(c(DateStart, DateEnd), ~replace(., Date > DateEnd, NA))) %>%
group_by(ID, DateStart, DateEnd) %>%
filter(is.na(DateStart) | row_number() == 1)
# ID Date DateStart DateEnd
# <int> <date> <date> <date>
#1 1 2021-02-11 2021-02-11 2021-02-17
#2 1 2021-02-18 NA NA
#3 1 2021-02-19 2021-02-19 2021-02-21
#4 2 2021-01-15 2021-01-15 2021-01-20
#5 2 2021-01-21 NA NA
#6 2 2021-01-22 NA NA
#7 2 2021-01-23 2021-01-23 2021-01-24
df <- structure(list(ID = c(1L, 1L, 2L, 2L), Date = c("2/11/2021",
"2/19/2021", "1/15/2021", "1/23/2021"), DateStart = c("2/11/2021",
"2/19/2021", "1/15/2021", "1/23/2021"), DateEnd = c("2/17/2021",
"2/21/2021", "1/20/2021", "1/24/2021")),
class = "data.frame", row.names = c(NA, -4L))