SAS中如何合并存在交叉的日期范围并更新FLAG标识?
在SAS中合并交叉日期范围并更新FLAG标识
需求说明:针对同一ID和PROV分组下存在交叉或重叠的日期范围记录,将其合并为一条记录,并将合并后的记录FLAG字段设置为OK。
原始数据集
ID PROV dt_entrata dt_uscita FLAG 381 00001 31/12/2004 09/11/2005 OK 381 00001 05/07/2011 16/04/2012 OK 381 00001 31/12/2013 20/10/2014 KO 381 00001 19/10/2014 15/02/2018 KO
目标数据集
ID PROV dt_entrata dt_uscita FLAG 381 00001 31/12/2004 09/11/2005 OK 381 00001 05/07/2011 16/04/2012 OK 381 00001 31/12/2013 15/02/2018 OK
SAS实现代码
步骤1:转换日期格式并排序
先把字符型日期转为SAS内置日期型变量(方便日期比较),再按ID、PROV和起始日期排序,确保同组记录按时间顺序排列。
/* 转换字符日期为SAS日期型,同时保留原格式显示 */ data sorted_data; set original_data; dt_entrata_sas = input(dt_entrata, ddmmyy10.); dt_uscita_sas = input(dt_uscita, ddmmyy10.); format dt_entrata_sas dt_uscita_sas ddmmyy10.; run; /* 按分组和起始日期排序 */ proc sort data=sorted_data; by ID PROV dt_entrata_sas; run;
步骤2:合并交叉/重叠日期范围
用数据步的分组逻辑,遍历同组记录,合并交叉或连续的日期区间,最终输出合并后的记录并设置FLAG为OK。
/* 合并交叉日期区间 */ data merged_data; set sorted_data; by ID PROV; retain current_start current_end; /* 分组第一条记录初始化当前区间 */ if first.PROV then do; current_start = dt_entrata_sas; current_end = dt_uscita_sas; end; else do; /* 当前记录与现有区间有交叉/重叠,合并区间 */ if dt_entrata_sas <= current_end then do; current_end = max(current_end, dt_uscita_sas); end; /* 无交叉,输出已合并的区间,再初始化新区间 */ else do; dt_entrata = put(current_start, ddmmyy10.); dt_uscita = put(current_end, ddmmyy10.); FLAG = 'OK'; output; current_start = dt_entrata_sas; current_end = dt_uscita_sas; end; end; /* 输出分组最后一条合并后的区间 */ if last.PROV then do; dt_entrata = put(current_start, ddmmyy10.); dt_uscita = put(current_end, ddmmyy10.); FLAG = 'OK'; output; end; /* 保留需要的输出字段 */ keep ID PROV dt_entrata dt_uscita FLAG; run;
代码说明
retain语句用于跨观测保留当前区间的起止日期,实现分组内的状态传递- 通过
first.PROV和last.PROV识别分组的首尾记录,处理分组初始化和收尾输出逻辑 - 当当前记录的起始日期不晚于现有区间的结束日期时,判定为交叉/重叠,更新区间结束日期为两者最大值
- 无交叉时输出已合并的区间,再开始新的区间统计
- 最后将SAS日期型变量转回原字符格式,保证输出格式与原始数据一致
内容的提问来源于stack exchange,提问作者Pier
相关产品推荐
相关产品推荐

