如何使用滞后函数计算SAS中的下一个观察值

时间:2014-12-30 09:17:58

标签: sas lag

假设数据集有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并没有像我预期的那样奏效。

3 个答案:

答案 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 IMLdo循环。我将您的表命名为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在迭代过程中非常有用且更直观。