SAS宏中的嵌套循环

时间:2016-01-14 22:54:58

标签: macros sas nested-loops

当我尝试在SAS中使用宏嵌套循环时出错:

%Let t1=30;
%Let t2=40;
%Let t3=50;
%Let t4=60;
%Let t5=70;

%macro Age(time);
%Do I = 1 %to &time.; 
data Milk&I;
set Milk;
/*If Age is less than 30, MilkF and MilkA after 30 should be 0, same for 40-70*/

where (age<&&t&I. and (%Do I = &I. %to 5;
                              MilkF&&t&I. ne 0 or MilkA&&t&I. ne 0 ; 
                        %end;) ) ;

run;
%end;
%mend Age;
%Age(5)

错误显示在最后一个&#34; ne 0;&#34;语法错误。 问题是什么?谢谢你的帮助!

更新: 我想要的宏的输出是(以t1 = 30为例):

where (age<30 and (
               MilkF30 ne 0 or MilkA30 ne 0 or 
               MilkF40 ne 0 or MilkA40 ne 0 or
               MilkF50 ne 0 or MilkA50 ne 0 or
               MilkF60 ne 0 or MilkA60 ne 0 or
               MilkF70 ne 0 or MilkA70 ne 0 
               ) ) ;

所以我已将代码更改为

where (age<&&t&I. and 
(%Do I = &I. %to 5;
 MilkFreq&&t&I. ne 0 or MilkAmnt&&t&I. ne 0 or
%end;
 ) ) ;

错误:

   ) ) ;  run;
  -
  22
  76

&#34;错误:解析WHERE子句时出现语法错误。&#34; 那么现在发生了什么?

1 个答案:

答案 0 :(得分:1)

我看到一些不同的错误。考虑:

where (age<&&t&I. and (%Do I = &I. %to 5;
                              MilkF&&t&I. ne 0 or MilkA&&t&I. ne 0 ; 
                        %end;) ) ;

这会产生:

where (age<30 and (
                   MilkF30 ne 0 or MilkA30 ne 0 ;
                   MilkF40 ne 0 or MilkA40 ne 0 ;
                   MilkF50 ne 0 or MilkA50 ne 0 ;
                   MilkF60 ne 0 or MilkA60 ne 0 ;
                   MilkF70 ne 0 or MilkA70 ne 0 ;
                   ) ) ;
  1. 如果查看生成的WHERE语句,由于额外的分号,它无效。这会导致错误消息。要解决此问题,请在MilkA&&t&I. ne 0 ;

  2. 末尾删除宏中的分号
  3. 这些OR条款的逻辑并不像我在评论中描述的那样,所以你可能想要检查。

  4. 正如@Reeza指出的那样,你正在使用计数器&amp; i在一个使用计数器&amp; i的循环中。这通常不会导致语法错误,但会导致外部循环过早退出,或者继续无限循环。所以你可以使用&amp; j作为内循环的迭代器。同样最好将&amp; i和&amp; j声明为宏的LOCAL,以避免与外部作用域中任何类似命名的宏变量发生冲突。

  5. 更新: 建议你启用OPTIONS MPRINT,然后查看宏生成的代码。通过编辑:

    where (age<&&t&I. and 
            (%do I = &I. %to 5;
               MilkFreq&&t&I. ne 0 or MilkAmnt&&t&I. ne 0 or
             %end;
             ) ) ;
    

    你现在有太多的OR,​​因为它会在最后产生一个额外的OR,即MilkFreq70 ne 0 or MilkAmnt70 ne 0 or ) )

    您可以尝试以下方式:

    where (age < &&t&i and 
            (%do j = &i %to 5;
               MilkFreq&&t&j ne 0 or MilkAmnt&&t&j ne 0 
               %if &j ne 5 %then or;
             %end;
             ) ) ;