使用LAG和LAST.VAR创建变量

时间:2012-10-10 13:55:35

标签: sas

我有以下数据集:

AGE    HSQ    PCT

65      1     0.7
65      2     0.2
65      3     0.1
66      1     0.5
66      2     0.25
66      3     0.25

[...]

我需要的是获得以下输出:

AGE     P1    P2     P3

65     0.7    0.2    0.1
66     0.5    0.25   0.25

[...]

我被告知采用LAG和FIRST.AGE或LAST.AGE来做到这一点,对我来说这似乎是一个很好的策略。但是我无法得到最终结果..我使用的(错误的)代码是:

DATA OUTPUT;
  SET SAMPLE;
    BY AGE HSQ;
  IF LAST.AGE THEN DO;
    P1=LAG2(PCT);
    P2=LAG1(PCT);
    P3=PCT;
  END;
RUN;

但它跳到了普通的年龄百分比,这不是我需要的..语法错误在哪里?谢谢!

2 个答案:

答案 0 :(得分:3)

有人告诉我这是一个使用它们的任务,或者这是最简单的方法吗?

最简单的方法是PROC TRANSPOSE:

data have;
input AGE    HSQ    PCT;
datalines;
65      1     0.7
65      2     0.2
65      3     0.1
66      1     0.5
66      2     0.25
66      3     0.25
;;;;
run;

proc transpose data=have out=want prefix=P;
by age;
var pct;
id hsq;
run;

LAG无法按您认为的方式工作 - 它为您提供上一行的值;它改为创建一个队列并获取(参数)的当前值,并为您提供队列中的先前值。所以你不能在这样的IF语句中使用它。

如果由于某种原因必须在datastep中执行此操作,那么您可能希望这样做:

data want;
array p[3];
do _n_ = 1 by 1 until (last.age);
    set have;
    by age;
    p[hsq]=pct;
end;
keep p1-p3 age;
run;

真的没有理由使用滞后或任何滞后的概念;就像你遇到属于某个地方的值一样,你将它们分配到那个地方,当你点击last.age然后输出。

是否有人想和我一起提出删除LAG功能的SASware请求?

答案 1 :(得分:2)

只是为了好玩,直接回答原始问题(以显示如何做到这一点):

DATA want;
  SET have;
    BY AGE HSQ;
    p1=lag2(pct);
    p2=lag1(pct);
    p3=pct;
    if last.age then output;
run;

这经历了很多额外的工作(当然,我的意思是几纳秒的CPU时间),因为它计算了六次滞后并且只输出了两个结果。这也有点“冒险”,因为它没有检查以确保HSQ是正确的值 - 即,如果你错过了一个年龄的一个条目,并且只有2行,那么你就有了上一年龄的HSQ = 3的值,这可能是不希望的。

最终的一点是,对于LAG,如果您打算将其用作“前一行记录”的替身,则需要将其保留在条件块之外。计算每个行的延迟,并有条件地使用结果(在这种情况下,有条件地使用输出)。