合并R中的连续日期范围
我想将观察结果合并到连续的日期范围内(所涵盖的天数没有间隔)。每个patid在生成的数据框中可能有多个范围。我知道可以使用loop来完成。但是,有没有有效的方法来处理此任务?请注意,这里的时间间隔没有重叠,并且开始日期正在增加 数据在这里(我使用R:dput,您可以在R中复制并分配给您的对象):合并R中的连续日期范围,r,R,我想将观察结果合并到连续的日期范围内(所涵盖的天数没有间隔)。每个patid在生成的数据框中可能有多个范围。我知道可以使用loop来完成。但是,有没有有效的方法来处理此任务?请注意,这里的时间间隔没有重叠,并且开始日期正在增加 数据在这里(我使用R:dput,您可以在R中复制并分配给您的对象): 一种data.table方法(使用magrittr以提高可读性)(稳健版): 一种tidyverse方法(非稳健、简单版本): 输出: # A tibble: 5 x 3 # Groups: p
一种
data.table
方法(使用magrittr
以提高可读性)(稳健版):
一种tidyverse
方法(非稳健、简单版本):
输出:
# A tibble: 5 x 3
# Groups: patid [3]
patid cont_start cont_end
<int> <date> <date>
1 1 2010-01-01 2010-05-31
2 2 2010-01-01 2010-03-31
3 2 2010-08-01 2010-09-30
4 3 2011-05-06 2011-06-15
5 3 2012-07-01 2012-12-01
#一个tible:5 x 3
#组别:patid[3]
患者控制开始控制结束
1 1 2010-01-01 2010-05-31
2 2 2010-01-01 2010-03-31
3 2 2010-08-01 2010-09-30
4 3 2011-05-06 2011-06-15
5 3 2012-07-01 2012-12-01
你的情况下的输出是相同的,但是如果在任何时候发生在序列中的开始日期都会有一个更高的结束日期而不是一个较迟的开始日期,那么你需要去做第一个(健壮的)方法(当然,如果你不认为这是一个错误)。
在这种情况下,健壮性与
data.table
或tidyverse
(您也可以通过重写tidyverse
版本来使用calc\u cummax
函数,但需要加载data.table
).帮助您在中共享示例更容易,因此我们可以复制/粘贴到R中进行测试。使用数据图片不是很有趣。谢谢,我学会了使用dput!
library(data.table)
library(magrittr)
calc_cummax <- function(x) (setattr(cummax(unclass(x)), "class", c("Date", "IDate")))
df_merged <- setDT(df) %>%
.[, `:=` (cont_start = as.Date(as.character(start_date), "%m/%d/%Y"),
cont_end = as.Date(as.character(end_date), "%m/%d/%Y"))] %>%
.[order(patid, start_date),] %>%
.[, max_until_now := shift(calc_cummax(cont_end)), by = patid] %>%
.[, lead_max := shift(max_until_now, type = "lead"), by = patid] %>%
.[is.na(max_until_now), max_until_now := lead_max, by = patid] %>%
.[(max_until_now + 1L) >= cont_start, gap_between_contracts := 0, by = patid] %>%
.[(max_until_now + 1L) < cont_start, gap_between_contracts := 1, by = patid] %>%
.[is.na(gap_between_contracts), gap_between_contracts := 0] %>%
.[, ("fakeidx") := cumsum(gap_between_contracts), by = patid] %>%
.[, .(cont_start = min(cont_start), cont_end = max(cont_end)), by = .(patid, fakeidx)] %>%
.[, ("fakeidx") := NULL]
patid cont_start cont_end
1: 1 2010-01-01 2010-05-31
2: 2 2010-01-01 2010-03-31
3: 2 2010-08-01 2010-09-30
4: 3 2011-05-06 2011-06-15
5: 3 2012-07-01 2012-12-01
library(tidyverse)
df %>%
mutate(
cont_start = as.Date(as.character(start_date), "%m/%d/%Y"),
cont_end = as.Date(as.character(end_date), "%m/%d/%Y")
) %>%
arrange(patid, cont_start) %>%
group_by(patid) %>%
mutate(
idx = cumsum(coalesce(as.numeric(cont_start != (lag(cont_end) + 1)), 0))
) %>%
group_by(patid, idx) %>%
summarise(
cont_start = min(cont_start),
cont_end = max(cont_end)
) %>% select(-idx)
# A tibble: 5 x 3
# Groups: patid [3]
patid cont_start cont_end
<int> <date> <date>
1 1 2010-01-01 2010-05-31
2 2 2010-01-01 2010-03-31
3 2 2010-08-01 2010-09-30
4 3 2011-05-06 2011-06-15
5 3 2012-07-01 2012-12-01