首页 > 解决方案 > SAS 和做循环

问题描述

我正在用 SAS 编写程序。

这是我拥有的数据集:

id huuse days  
1   0   4  
1   0   3  
1   1   12    
1   1   1  
1   2   15  
2   1   13  
2   0   16  
2   1   18  
2   0   44

对于每个 ID,如果变量 ne 1,我想删除记录huuse,直到我到达第一个huuse=1。然后我想保留该记录以及该 ID 的所有后续记录,无论值huuse是什么。因此id=1,我想删除前两条记录,而不是保留id=1从第三条记录开始的所有记录。因为id=2,第一条记录已经有了huuse=1,所以我想保留所有记录id=2

我想要的数据集应该是这样的:

id huuse days  
1   0   4  
1   0   3  
1   1   12  
1   1   1  
1   2   15  
2   1   13  
2   0   16  
2   1   18  
2   0   44  

我尝试了此代码,但它删除了所有具有 huuse ne 1 的记录。

data want;  
set have;  
by id;  
do until (huuse=1);  
if huuse = 1 then LEAVE;            
if huuse ne 1 then DELETE;  
END;  
run;  

我尝试了几种 do 循环的变体,但它们都做同样的事情。

标签: sas

解决方案


DATA步骤是一个带有隐式循环的程序,它读取SET语句中指定的数据集的每条记录。默认情况下,任何不来自数据集的程序数据向量 (pdv) 变量都会在隐式循环的顶部重置为缺失。RETAIN您可以使用一条语句来命名不应重置的变量来更改该行为。

因此,在您的问题中,您有两种需要跟踪变量的情况。该变量将跟踪条件的状态huuse=1在这个组中见过吗?. 调用这个变量one_flag

  • RETAIN one_flag;所以你可以控制它的价值何时改变
  • BY组开始时one_flag需要重置为 false ( 0)
  • 何时huuse首次看到1将标志设置为 true ( 1)

例子:

data want(drop=one_flag);
  set have;
  by id;

  retain one_flag 0;

  if first.id then one_flag = 0;

  if not one_flag and huuse = 1 then one_flag = 1;

  if one_flag then OUTPUT;   * want all rows in group starting at first huuse=1;
run;

您可以将SETandBY语句放在显式DO中,这会改变程序的操作行为,尤其是在显式循环根据LAST.<var>自动变量终止的情况下。这样的循环通常被 SAS 程序员称为 DOW 循环。SAS 文档中没有短语DOW 循环

例子:

data want;
  do until (last.id);
    set have;
    by id;

    if not one_flag and huuse=1 then one_flag = 1;

    if one_flag then OUTPUT;   * want all rows in group starting at first huuse=1;
  end;
run;

因为循环是显式的,并且在循环中永远不会到达程序的 TOP,所以不需要RETAIN标志变量,也不需要重置它。未保留的程序变量在程序顶部自动重置,并且仅在BY组开始时到达程序顶部。在 SGF 2013 论文“The Magnificent DO”中了解有关此编程结构的更多信息,Paul M. Dorfman


推荐阅读