根据日期查找超过一年的疗程休息时间
Find treatment course breaks longer than a year based on dates
我有一个包含 ID 和治疗日期的数据框,如下所示
ID Dates
1 01/2/2012
1 02/8/2012
1 03/8/2012
1 04/5/2013
1 05/5/2013
2 01/2/2012
2 03/5/2013
2 04/6/2013
如果有超过一年的治疗日期中断,我需要为每个 ID 查找。如果是,那么我需要将它们分成两门课程,并列出开始和结束日期。所以执行 R 代码后,它将如下所示:
ID Course1StarteDate Course1EndDate Break1to2(Yr) Course2StartDate Course2EndDate
1 01/2/2012 03/8/2012 1.075 04/5/2013 05/5/2013
2 01/2/2012 01/2/2012 1.173 03/5/2013 04/6/2013
我的dataframe有几百个ID,不知道会有多少课程。有没有一种有效的方法可以使用 R 来解决这个问题?提前致谢!
如果 d
是您的数据,您可以确定一行日期与前一行日期之间的差异何时超过 365(或可能是 365.25),然后使用 cumsum
生成不同的疗程。最后添加一列,估计课程之间“休息”的持续时间。
as_tibble(d) %>%
group_by(ID) %>%
mutate(trt=as.numeric(Dates-lag(Dates)),
trt=cumsum(if_else(is.na(trt),0,trt)>365)+1) %>%
group_by(ID,trt) %>%
summarize(StartDate = min(Dates),
EndDate = max(Dates),.groups = "drop_last") %>%
mutate(Break:=as.numeric(lead(StartDate) - EndDate)/365)
输出:
ID trt StartDate EndDate Break
<dbl> <dbl> <date> <date> <dbl>
1 1 1 2012-01-02 2012-03-08 1.08
2 1 2 2013-04-05 2013-05-05 NA
3 2 1 2012-01-02 2012-01-02 1.17
4 2 2 2013-03-05 2013-04-06 NA
我建议保持这种长格式,而不是像您在示例中那样转为宽格式,尤其是在有数百个 ID 的情况下,所有 ID 都可能包含不同数量的课程。长格式几乎总是更好。
但是,如果你真的想要这个,你可以从上面继续管道,像这样:
ungroup %>%
pivot_wider(id_cols =ID,
names_from = trt,
values_from = c(StartDate:Break),
names_glue = "Course{trt}_{.value}",
names_vary = "slowest")
生成这种“宽幅”格式:
ID Course1_StartDate Course1_EndDate Course1_Break Course2_StartDate Course2_EndDate Course2_Break
<dbl> <date> <date> <dbl> <date> <date> <dbl>
1 1 2012-01-02 2012-03-08 1.08 2013-04-05 2013-05-05 NA
2 2 2012-01-02 2012-01-02 1.17 2013-03-05 2013-04-06 NA
我有一个包含 ID 和治疗日期的数据框,如下所示
ID Dates
1 01/2/2012
1 02/8/2012
1 03/8/2012
1 04/5/2013
1 05/5/2013
2 01/2/2012
2 03/5/2013
2 04/6/2013
如果有超过一年的治疗日期中断,我需要为每个 ID 查找。如果是,那么我需要将它们分成两门课程,并列出开始和结束日期。所以执行 R 代码后,它将如下所示:
ID Course1StarteDate Course1EndDate Break1to2(Yr) Course2StartDate Course2EndDate
1 01/2/2012 03/8/2012 1.075 04/5/2013 05/5/2013
2 01/2/2012 01/2/2012 1.173 03/5/2013 04/6/2013
我的dataframe有几百个ID,不知道会有多少课程。有没有一种有效的方法可以使用 R 来解决这个问题?提前致谢!
如果 d
是您的数据,您可以确定一行日期与前一行日期之间的差异何时超过 365(或可能是 365.25),然后使用 cumsum
生成不同的疗程。最后添加一列,估计课程之间“休息”的持续时间。
as_tibble(d) %>%
group_by(ID) %>%
mutate(trt=as.numeric(Dates-lag(Dates)),
trt=cumsum(if_else(is.na(trt),0,trt)>365)+1) %>%
group_by(ID,trt) %>%
summarize(StartDate = min(Dates),
EndDate = max(Dates),.groups = "drop_last") %>%
mutate(Break:=as.numeric(lead(StartDate) - EndDate)/365)
输出:
ID trt StartDate EndDate Break
<dbl> <dbl> <date> <date> <dbl>
1 1 1 2012-01-02 2012-03-08 1.08
2 1 2 2013-04-05 2013-05-05 NA
3 2 1 2012-01-02 2012-01-02 1.17
4 2 2 2013-03-05 2013-04-06 NA
我建议保持这种长格式,而不是像您在示例中那样转为宽格式,尤其是在有数百个 ID 的情况下,所有 ID 都可能包含不同数量的课程。长格式几乎总是更好。
但是,如果你真的想要这个,你可以从上面继续管道,像这样:
ungroup %>%
pivot_wider(id_cols =ID,
names_from = trt,
values_from = c(StartDate:Break),
names_glue = "Course{trt}_{.value}",
names_vary = "slowest")
生成这种“宽幅”格式:
ID Course1_StartDate Course1_EndDate Course1_Break Course2_StartDate Course2_EndDate Course2_Break
<dbl> <date> <date> <dbl> <date> <date> <dbl>
1 1 2012-01-02 2012-03-08 1.08 2013-04-05 2013-05-05 NA
2 2 2012-01-02 2012-01-02 1.17 2013-03-05 2013-04-06 NA