原始数据集如下:
sub month y
1 1 1
1 2 2
1 3 3
1 5 5
我想要的是根据每个主题的月份获得之前的3个y,如果该月份缺少y,那么新变量也是.
。例如,对于上面的例子,lag1是上个月的前一个y
,lag2
是2个月前的前一次y,lag3
是迄今为止的:
sub month y lag1 lag2 lag3
1 1 1 . . .
1 2 2 1 . .
1 3 3 2 1 .
1 5 5 . 3 2
问题是我检查了lag
和dif
函数,但在我的情况下,我想要的lag
取决于month
,而且月份之间也有间隔,所以我不能像lag1
函数那样使用前一个。
此外,我还需要为许多科目做这件事。谢谢
SQL解决方案:
data have;
input sub month y;
datalines;
1 1 1
1 2 2
1 3 3
1 5 5
;;;;
run;
proc sql;
create table want as
select H.sub,H.month, H.y, One.y as lag1, Two.y as lag2, Three.y as lag3
from have H
left join (select * from have) One on H.sub=One.sub and H.month=One.month+1
left join (select * from have) Two on H.sub=two.sub and H.month=Two.month+2
left join (select * from have) Three on H.sub=three.sub and H.month=Three.month+3
;
quit;
显然,如果你想要36个,这会有点长,但至少没有那么复杂。还有其他各种方法可以做到这一点。不要使用LAG,这会让人头疼,而且无论如何都不合适。如果您熟悉哈希的概念,那么哈希表可能更高效,并且需要更少的编码。
哈希解决方案:
data want;
if _n_ = 1 then do;
declare hash h(dataset:'have(rename=y=ly)');
h.defineKey('sub','month');
h.defineData('ly');
h.defineDone();
call missing(sub,month,ly);
end;
set have;
array lags lag1-lag3;
do prevmonth = month-1 to month-3 by -1;
if prevmonth le 0 then leave;
rc=h.find(key:sub,key:prevmonth);
if rc=0 then lags[month-prevmonth] = ly;
call missing(ly);
end;
run;
这很容易扩展到36[或其他]-只需将数组的长度更改为array lags lag1-lag36
和do语句do prevmonth=month-1 to month-36 by -1;
。您可能需要做的最多的工作就是安排事情,使month在这里工作-可以创建一个整数月份,也可以更改循环条件以使用month/year或其他类似的内容。你没有显示你的数据是如何指定的,所以在那里没有帮助。