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;
  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 循环您必须自己完成(您必须在其中放置一个 OUTPUT 语句,例如,如果您想要全部 8 个,则必须测试 EOF 和 STOP`(如果为 true)。

但也许这就是您想要的 - 您希望一开始没有任何值(value),然后您想做点什么。这就是 DoW 循环有用的时候。

嵌套的 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 循环“首先”在读取第一行之前执行操作 - 这又可能有帮助,也可能没有帮助,具体取决于您的用例。我认为我从未有过这样的用例,但这当然不是不可能的。

这是一个有用的案例,例如您基本上是手动执行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 循环最有用,它对于汇总然后在同一数据步骤迭代上读取汇总值非常有用。这是相同的摘要,但允许您查看当前行的值。如果您想查看差异,请将 have 中的 Z 值更改为其他值(我故意将它们设置为模式中的 1/2,以便更容易检查)。

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;

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

关于loops - SAS中嵌套道循环的解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45615466/

相关文章:

c++ - 删除 C++ 中的尾随逗号

sas - 解析哈希声明中的宏变量?

csv - 高效地将 SAS 数据集转换为 CSV

date - 如何在 SAS 中将日期值从日转换为季度

sas - SAS 中的连续月份数据计数

java - 检查无限调用/递归调用算法

r - n 列减法数

JAVA帮助获取输入的总和

css - 用 $.each 每隔一行改变颜色

merge - 在 sas 中创建虚拟变量以指示第一次出现观察