在R中按ID和年份合并(collapse)数据以生成平滑时间线的方法求助
解决R中按ID和状态合并连续时间区间的问题
我明白你需要将同一个ID下同一State的重叠/连续时间区间合并成平滑的时间线,下面是两种实用的R解决方案,分别基于dplyr(适合常规数据处理)和data.table(适合大数据集)。
第一步:构造示例数据
先把你的示例数据转换成R可处理的格式:
df <- data.frame( ID = c(1,1,1,1,1,1,1,1,1,2,2,2,2), From = c(2004,2005,2005,2012,2015,2012,2013,2016,2019,2003,2004,2008,2013), To = c(2005,2005,2012,2015,2020,2013,2016,2019,2020,2004,2008,2013,2015), State = c("MD","MD","DC","DC","DC","MD","MD","MD","MD","OR","OR","AZ","AZ") )
方法一:使用dplyr包(推荐,代码易读)
这个方法通过分组、标记连续区间、聚合三个步骤完成:
library(dplyr) df_cleaned <- df %>% # 按ID和State分组,确保每组内按起始时间排序 group_by(ID, State) %>% arrange(From, .by_group = TRUE) %>% # 标记连续/重叠的区间:当前区间的起始时间大于上一个区间的结束时间则新建分组 mutate( group_id = cumsum(From > lag(To, default = first(From) - 1)) ) %>% # 对每个子分组取最小起始时间和最大结束时间 group_by(ID, State, group_id) %>% summarise( From = min(From), To = max(To), .groups = "drop" ) %>% # 清理列并排序 select(-group_id) %>% arrange(ID, From) # 查看结果 print(df_cleaned)
逻辑解释:
arrange(From, .by_group = TRUE):确保每个ID+State组合下的区间按起始时间排序,这是判断连续性的前提。cumsum(From > lag(To, ...)):用累积求和生成分组ID,当当前区间的起始时间晚于上一个区间的结束时间时,说明是新的独立区间,分组ID加1;默认值处理第一个区间的边界情况。summarise:把同一个分组内的区间合并,取最早的起始时间和最晚的结束时间。
方法二:使用data.table包(适合大数据)
如果你的数据集非常大,data.table的处理速度会更快:
library(data.table) setDT(df) df_cleaned_dt <- df[order(ID, State, From), .(group_id = cumsum(From > shift(To, fill = first(From)-1))), by = .(ID, State)][ , .(From = min(From), To = max(To)), by = .(ID, State, group_id)][ , group_id := NULL][order(ID, From)] # 查看结果 print(df_cleaned_dt)
最终结果
两种方法都会得到你想要的平滑时间线:
ID State From To 1 1 MD 2004 2005 2 1 DC 2005 2020 3 1 MD 2012 2020 4 2 OR 2003 2008 5 2 AZ 2008 2015
内容的提问来源于stack exchange,提问作者bison2178
相关产品推荐
相关产品推荐

