创建有条件的新变量[sas]

时间:2013-02-08 21:35:43

标签: sas

原始数据集如:

sub month y
1   1     1
1   2     2
1   3     3
1   5     5 

我想要的是根据每个主题的月份获得前3个月,如果在该月缺少y,那么新变量也是.。比方说,对于上面的例子,上一个例子中,lag1是前一个y,{2}前一个是lag2lag3到目前为止是这样的:

sub month y lag1 lag2 lag3
1   1     1  .    .    .
1   2     2  1    .    .
1   3     3  2    1    .
1   5     5  .    3    2 

问题是我检查了lagdif功能,但在我的情况下,lag上我想要的内容取决于month,并且月份之间也存在差距,所以我不能使用像lag1函数那样的前一个。

我也需要为很多科目做这件事。感谢。

1 个答案:

答案 0 :(得分:2)

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;您可能需要做的最多工作是安排事情所以月在这里工作 - 通过创建整数月,或更改循环标准以使用月/年或诸如此类。您没有显示数据的指定方式,因此无法帮助您。