假设数据集有3列
Obs Theo Cal
1 20 20
2 21 23
3 21 .
4 22 .
5 21 .
6 23 .
Theo
是理论值,而Cal
是估算值。
我需要计算丢失的Cal
。
对于每个Obs
,其Cal
是前两个Cal
值的线性组合。
Cal(3) = Cal(2) * &coef1 + Cal(1) * &coef2
。
Cal(4) = Cal(3) * &coef1 + Cal(2) * &coef2
。
但Cal = lag1(Cal) * &coef1 + lag2(Cal) * &coef2
并没有像我预期的那样奏效。
答案 0 :(得分:3)
使用滞后的问题是当你使用lag1(Cal)时你没有得到写入输出数据集的Cal的最后一个值,你得到传递给输出数据集的最后一个值。 lag1功能。 使用保留可能更容易,如下所示:
data want(drop=Cal_l:);
set have;
retain Cal_l1 Cal_l2;
if missing(Cal) then Cal = Cal_l1 * &coef1 + Cal_l2 * &coef2;
Cal_l2 = Cal_l1;
Cal_l1 = Cal;
run;
答案 1 :(得分:1)
我猜你会写一个像这样的datastep。
data want;
set have;
if missing(cal) then
cal = lag1(cal)*&coef1 + lag2(cal)*&coef2;
run;
LAG并没有抓住以前的值,而是创建一个N长的队列,并为您提供结束。如果你把它放在IF语句后面,那么你永远不会把CAL的有用值放到那个队列中 - 你只会丢失错误。像这样看:
data have;
do x=1 to 10;
output;
end;
run;
data want;
set have;
real_lagx = lag(x);
if mod(x,2)=0 then do;
not_lagx = lag(x);
put real_lagx= not_lagx=;
end;
run;
Real滞后是最后一个值,而NOT滞后是最后偶数值,因为它们位于IF内。
这里有两个主要选择。使用RETAIN跟踪最后两个观察结果,或者像在IF语句之前使用LAG一样使用LAG,然后使用IF语句中的滞后值。任何一种方法都没有任何内在的好坏;只要您理解LAG,LAG就能发挥作用。 RETAIN通常被认为是“更安全”,因为它更难搞砸;你也可以更容易地看到自己在做什么。
data want;
set have;
retain cal1 cal2;
if missing(cal) then cal=cal1*&coef1+cal2*&coef2;
output;
cal2=cal1;
cal1=cal;
run;
或
data want;
set have;
cal1=lag1(cal);
cal2=lag2(cal);
if missing(cal) then cal=cal1*&coef1+cal2*&coef2;
run;
后一种方法只有在cal
不经常丢失的情况下才会起作用 - 特别是如果它从任何三次观察中都不会丢失多次。在最初的示例中,将填充第一个cal
(第3行),但从那里开始它将始终丢失。这可能是也可能不是;如果不是,请使用retain
。
答案 2 :(得分:0)
可能有一种方法可以在DATA
步骤中完成它,但就我而言,当我希望SAS迭代处理时,我使用PROC IML
和do
循环。我将您的表命名为SO
并成功运行以下内容:
PROC IML;
use SO; /* create a matrix from your table to be used in proc iml */
read all var _all_ into table;
close SO;
Cal=table[,3];
do i=3 to nrow(cal); /* process iteratively the calculations */
if cal[i]=. then do;cal[i]=&coef1.*cal[i-1]+&coef2.*cal[i-2];
end;else do;end;
end;
table[,3]=cal;
Varnames={"Obs" "Theo" "Cal"};
create SO_ok from table [colname=varnames]; /* outputs a new table */
append from table;
close SO_ok;
QUIT;
我并不是说你不能用lag()
和DATA
步骤来实现你想做的事情。但我发现PROC IML
在迭代过程中非常有用且更直观。