Loops SAS中嵌套dow循环的说明

Loops SAS中嵌套dow循环的说明,loops,sas,Loops,Sas,我想知道下面的伪代码是如何工作的?如果有一个成功的例子,我将不胜感激 data want; do until (last.var1); do until (last.var2); set have; * other sas statements; end; end; run; 基本上,单个DoW循环允许您在每个变量边界之后执行特定操作,并且与正常数据步骤的计时略有不同(这可能有用,也可能没有)。因此,考虑到这一组: data have; i

我想知道下面的伪代码是如何工作的?如果有一个成功的例子,我将不胜感激

data want;
  do until (last.var1);
    do until (last.var2);
      set have;

      * other sas statements;

    end;
 end;
run;

基本上,单个DoW循环允许您在每个变量边界之后执行特定操作,并且与正常数据步骤的计时略有不同(这可能有用,也可能没有)。因此,考虑到这一组:

data have;
  input x y z;
  datalines;
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
;;;;
run;
以下是正常数据步骤:

data want;
  set have;
  by x;
  if first.x then do;
    put "First value of " x=;
  end;
  put _all_;
  if last.x then do;
    put "Last value of " x=;
  end;
run;
以下是道琼斯指数:

data want_dow;
  put "First value of " x=;
  do _n_ = 1 by 1 until (last.x);
    set have;
    by x;
    put _all_;
  end;
  put "Last value of " x=;
run;
请注意,它的结果略有不同-对于第一次迭代和最后一次迭代,它输出不同的行。这是因为SAS在第一种方法中自动为我们做所有这些事情,而DoW loop你必须自己做(例如,如果你想要全部8个,你必须在那里放一个
OUTPUT
语句,并且你必须测试
EOF和
STOP`if true)

但也许这就是你想要的——你希望一开始没有价值,然后你想做点什么。这就是道循环有用的时候

嵌套的DoW循环是相同的,只是可以在两个不同的点上执行操作。请注意,它实际上并没有改变读取行的方式:每次运行到
set
语句时,都会从数据集中读取下一行(无论该行是什么)。同样的顺序,只是你有更多的停止点让你写代码

data want;
  set have;
  by x y;
  if first.x then do;
    put "First value of " x=;
  end;
  if first.y then do;
    put "First value of " y=;
  end;
  put _all_;
  if last.y then do;
    put "Last value of " y=;
  end;
  if last.x then do;
    put "Last value of " x=;
  end;

run;

data want_dow;
  put "First value of " x=;
  do _n_ = 1 by 1 until (last.x);
    put "First value of " y=;
    do _n_ = 1 by 1 until (last.y);
      set have;
      by x y;
      put _all_;
    end;
    put "Last value of " y=;
  end;
  put "Last value of " x=;
run;
同样,这里也存在差异,因为DoW循环“first”在读取第一行之前执行操作,这也可能有帮助,也可能没有帮助,这取决于您的用例。我不认为我曾经有过这样的用例,但这肯定不是不可能的

这里有一个有用的例子,你基本上是手工做一个
PROC MEANS
。当然,这两种方法都可以做到;有些人会喜欢每一种

data want_dow;    
  do _n_ = 1 by 1 until (last.x);
    do _n_ = 1 by 1 until (last.y);
      set have;
      by x y;
      z_sum_y = sum(z_sum_y,z);
      z_sum_x = sum(z_sum_x,z);
    end;
    z_sum = z_sum_y;
    output;
    call missing(z_sum_y);
  end;
  call missing(y);
  z_sum = z_sum_x;
  output;
  drop z_sum_y z_sum_x;
run;

data want;
  set have;
  by x y;
  z_sum_y+z;
  z_sum_x+z;
  if last.y then do;
    z_sum = z_sum_y;
    output;
    z_sum_y=0;
  end;
  if last.x then do;
    z_sum = z_sum_x;
    call missing(y);
    output;
    z_sum_x=0;
  end;
  drop z_sum_y z_sum_x;
run;
不过,DoW循环对Double DoW循环最为有用,DoW循环用于汇总,然后在同一数据步迭代中读取汇总值。这是相同的摘要,但允许您查看当前行上的值。如果您想看到差异,可以将have中的Z值更改为其他值(我有意将它们设置为patterns中的1/2,以便更容易检查)

要在没有双道循环的情况下实现这一点,您必须将第一个
want
的结果合并回
have
。这不一定是什么大问题,但这是数据的第二次传递;Double DoW循环利用缓冲来避免实际重新执行第二次读入的I/O

data want_ddow;
  array z_sum_ys[2] _temporary_;
  do _n_ = 1 by 1 until (last.x);
    do _n_ = 1 by 1 until (last.y);
      set have;
      by x y;
      z_sum_ys[y] = sum(z_sum_ys[y],z);
      z_sum_x = sum(z_sum_x,z);
    end;
  end;

  do _n_ = 1 by 1 until (last.x);  *do not need nesting here;
    set have;
    by x y;
    z_sum_y = z_sum_ys[y];
    output;
  end;
  call missing(of z_sum_ys[*] z_sum_x);
run;