我有以下数据集:
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;
但它跳到了普通的年龄百分比,这不是我需要的..语法错误在哪里?谢谢!
答案 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,如果您打算将其用作“前一行记录”的替身,则需要将其保留在条件块之外。计算每个行的延迟,并有条件地使用结果(在这种情况下,有条件地使用输出)。