SAS为纵向数据添加新观测值
我在SAS中有一个纵向数据集,时间段分为事件风险期和非风险期。不幸的是,有些时间段是重叠的,我想把它们重新编码成一个完全不重叠的观测数据集。例如,数据集当前看起来像:SAS为纵向数据添加新观测值,sas,Sas,我在SAS中有一个纵向数据集,时间段分为事件风险期和非风险期。不幸的是,有些时间段是重叠的,我想把它们重新编码成一个完全不重叠的观测数据集。例如,数据集当前看起来像: Row 1: ID=123; Start=Jan 1, 1999; End=Dec 31, 1999; At_risk="Yes" Row 2: ID=123; Start=Feb 1, 1999; End=Feb 15, 1999; At_risk="No" Row 1: ID=123; Start=Jan 1, 1999;
Row 1: ID=123; Start=Jan 1, 1999; End=Dec 31, 1999; At_risk="Yes"
Row 2: ID=123; Start=Feb 1, 1999; End=Feb 15, 1999; At_risk="No"
Row 1: ID=123; Start=Jan 1, 1999; End=Feb 1, 1999; At_risk="Yes"
Row 2: ID=123; Start=Feb 1, 1999; End=Feb 15, 1999; At_risk="No"
Row 3: ID=123; Start=Feb 15, 1999; End=Dec 31, 1999; At_risk="Yes"
我想要的数据集如下所示:
Row 1: ID=123; Start=Jan 1, 1999; End=Dec 31, 1999; At_risk="Yes"
Row 2: ID=123; Start=Feb 1, 1999; End=Feb 15, 1999; At_risk="No"
Row 1: ID=123; Start=Jan 1, 1999; End=Feb 1, 1999; At_risk="Yes"
Row 2: ID=123; Start=Feb 1, 1999; End=Feb 15, 1999; At_risk="No"
Row 3: ID=123; Start=Feb 15, 1999; End=Dec 31, 1999; At_risk="Yes"
想法?这些任务是调试程序逻辑和对抗数据假设、玩新旧值的练习。。。 下面是您提供的确切示例的初始代码,我肯定需要对实际数据进行一些调整 如果有超过当前下一条记录的时间重叠,我不确定这样做是否可行(通过合理的努力)。在这种情况下,您可能会更有效地将原始的开始-结束时间间隔拆分为一天级别,然后将详细信息汇总到新的时间间隔
data orig;
format Id 16. Start End Date9.;
Id = 123;Start='1jan1999'd; End='31dec1999'd; At_risk="Yes";output;
Id = 123;Start='1feb1999'd; End='15feb1999'd; At_risk="No";output;
run;
proc sort data = orig;
by ID Start;
run;
data modified;
format pStart oStart pEnd oEnd Date9.;
set orig;
length pStart pEnd 8 pAt_risk $3;
by ID descending End ;
retain pStart pEnd pAt_risk;
/* keep original values */
oStart = Start;
oEnd = End;
oAt_risk = At_risk;
if first.id then do;
pStart = Start;
pEnd = End;
pAt_risk = At_risk;
/* no output */
end;
else do;
if pAt_risk ne At_risk then do;
if Start > pStart then do;
put _all_;
Start = pStart;
End = oStart;
At_risk = pAt_risk;
output;/* first part of time span */
Start = oStart;
End = oEnd;
At_risk = oAt_risk;
output;/* second part of time span */
if (End < pEnd ) then do;
Start = End;
End = pEnd;
At_risk = pAt_risk;
output; /*third part of time span */
/* keep current values as previous record values */
pStart = max(oStart, Start);
pEnd = End;
pAt_risk = At_risk;
end;
end;
end;
end;
run;
proc print;run;
数据源;
格式Id 16。起止日期9。;
Id=123;1999年1月1日开始;完一九九九年十二月三十一日;;风险=“是”;产出;
Id=123;1999年6月1日开始;完一九九九年二月十五日;;风险=“否”;产出;
跑
proc sort data=orig;
按ID开始;
跑
数据修改;
格式pStart oStart pEnd oEnd Date9。;
设定原点;
长度pStart pEnd 8帕特鲁风险3美元;
由ID下降结束;
保留pStart pEnd pAt_风险;
/*保持原值*/
oStart=启动;
oEnd=结束;
oAt_风险=有风险;
如果是第一个,那么就做;
pStart=开始;
pEnd=结束;
pAt_风险=有风险;
/*无输出*/
结束;
否则你会;
如果pAt_risk ne处于风险中,那么就这样做;
如果开始>开始,则执行;
把所有的东西都放进去;
开始=pStart;
结束=静态启动;
有风险=无风险;
输出;/*时间跨度的第一部分*/
开始=停止;
结束=结束;
风险=oAt风险;
输出;/*时间跨度的第二部分*/
如果(结束<等待),则执行;
开始=结束;
结束=挂起;
有风险=无风险;
产出/*时间跨度的第三部分*/
/*将当前值保留为以前的记录值*/
pStart=最大值(静态启动,启动);
pEnd=结束;
pAt_风险=有风险;
结束;
结束;
结束;
结束;
跑
过程打印;跑
Vasja可能已经提出了类似这样的建议(日期级别)作为替代方案
在这里,我假设在纵向数据集中读取的最近一行将优先于日期范围重叠的任何其他行。如果情况并非如此,则根据需要调整以下优先级推导
你确定你的开始和结束日期是正确的吗。您想要的输出仍然有重叠的日期。2月1日和15日既有风险也没有风险。您的结束日期应至少比下一个开始日期早一天。不是同一天。结束日期和开始日期应该是连续的。因此,编写一个能够产生所需输出(日期重叠)的解决方案是有问题的。以下解决方案基于无重叠日期。您需要根据所需的输出修改它以包括重叠的日期
/* Your longitudinal dataset . */
data orig;
format Id 16. Start End Date9.;
Id = 123;Start='1jan1999'd; End='31dec1999'd; At_risk="Yes";output;
Id = 123;Start='1feb1999'd; End='15feb1999'd; At_risk="No";output;
run;
/* generate a row for each date between start and end dates. */
/* Use row number (_n_) to assign priorioty. */
Data overlapping_dates;
set orig;
foramt date date9.;
priority = _n_;
do date = start to end by 1;
output;
end;
Run;
/* Get at_risk details for most recent read date according to priority. */
Proc sql;
create table non_overlapping_dates as
select id, date, at_risk
from overlapping_dates
group by id, date
having priority eq max (priority)
order by id, date
;
Quit;
/* Rebuild longitudinal dataset . */
Data longitudinal_dataset
(keep= id start end at_risk)
;
format id 16. Start End Date9. at_risk $3.;
set non_overlapping_dates;
by id at_risk notsorted;
retain start;
if first.at_risk
then start = date;
/* output a row to longitudinal dataset if at_risk is about to change or last row for id. */
if last.at_risk
then do;
end = date;
output;
end;
Run;
你有ETS许可证吗?是的,不幸的是,除了当前的下一个记录之外还有其他重叠。不过,你关于将间隔时间分成几天的建议是正确的。谢谢