我使用下面的代码来识别和输出前三年。为了提供更多的细节,样本包括多个人ID和每个人ID在多年内的观察结果。最后的样本只保留至少有前三年(如2001年、2002年、2003年)的个人身份证。
data have3 ;
set have2;
by personid;
set have2 ( firstobs = 2 keep = year rename = (year = _year2) )
have2 ( obs = 1 drop = _all_ );
_year2 = ifn( last.personid, (.), _year2 ); /*output the value of next year*/
set have2 ( firstobs = 3 keep = year rename = (year = _year3) )
have2 ( obs = 2 drop = _all_ );
_year3 = ifn( last.personid, (.), _year3 ); /*output the value of the year after the next year*/
_prev1 = ifn( first.personid, (.), lag(year) ); /*output the value of previous year*/
_prev2 = ifn( first.personid, (.), lag2(year) );/*output the value of the year before the previous year*/
if (year-2 eq _prev1-1 eq _prev2) or
(year+2 eq _year2+1 eq _year3) or
(year eq _year2-1 eq _prev1+1) then output;
run;这段代码在大多数情况下都很好。然而,我的样本有一些棘手的情况。下图显示了其中一种情况。第488号个人身份证只有两项观察(1994年和1995年)。不幸的是,下一个人身份证489的第一年是1996年。因此,_year3 of ID488 Year1994是使year+2 eq _year2+1 eq _year3成为现实的1996年。结果,ID488 Year1994也输出到最后的示例。如何改进代码以避免这种情况?谢谢!

发布于 2020-02-01 22:05:18
只需将id变量保留在您的前瞻性SET语句中可能会更容易。
set have2(firstobs=2 keep=personid year rename=(personid=personid2 year=_year2))...
set have2(firstobs=3 keep=personid year rename=(personid=personid3 year=_year3))...然后,您可以确保下一个和下一个-下一个记录实际上是为同一个人。
if personid ne personid2 then _year2=.;
if personid ne personid3 then _year3=.;你的回溯变量也是一样的。
_prev1=lag(year);
_prev2=lag2(year);
if personid ne lag(personid) then _prev1=.;
if personid ne lag2(personid) then _prev2=.;发布于 2020-02-02 11:21:49
SQL查询可能更清楚:
%* group has at least 3 years;
create table want as
select *
from have
group by id
having count(distinct year) >= 3道氏圈可以计算一个状态变量,该变量表示该组在某个时间内运行了3年。
%* group has a run of 3 years somewhere in time;
data want;
do _n_ = 1 by 1 until (last.id);
set have;
by id;
if _n_ >= 3 and lag2(year)+1 = lag(year) and lag(year)+1 = year then
_group_has_3_consective_years = 1;
end;
do _n_ = 1 to _n_;
set have;
if _group_has_3_consective_years then OUTPUT;
end;
drop _:;
run;道氏循环还可以计算出更复杂的情况下的状态变量,即希望从运行3年的组中获得数据,这些数据在组的最后一年结束。
%* group has a run of 3 years finishing at end time;
data want_3_ending;
do _n_ = 1 by 1 until (last.id);
set have;
by id;
if _n_ >= 3 and lag2(year)+1 = lag(year) and lag(year)+1 = year then do;
_group_has_3_consective_years = 1;
_end_at_year = year;
end;
end;
_top_year = year;
do _n_ = 1 to _n_;
set have;
if _group_has_3_consective_years and _end_at_year = _top_year then OUTPUT;
end;
drop _:;
run;注意:LAG调用总是被解析的,因为SAS if语句做而不是做快捷逻辑计算。_N_ >= 3确保延迟都来自同一组。
https://stackoverflow.com/questions/60021313
复制相似问题