7

我正在寻找SAS 9.3 宏语言中for in循环(如在Python或 R 中)的等价物。DO 循环似乎是解决方案,但并没有完全按照我的意愿工作。我建立了一种在数据步骤中使用DO 循环执行此操作的方法,但它不适用于宏语言。例如,在数据步骤中,此代码正在运行:

DATA _NULL_;
  DO i = 1,3,5,9;
    PUT i;
  END;
RUN;

然后按预期出现日志提示:

1
3
5
9

当我尝试对宏中的%DO循环执行相同操作时,出现错误。

%MACRO test();
  %DO i = 1,2,4,9 ;
    %PUT i = &i;
  %END;
%MEND;

%test();

日志提示这些消息:

ERROR: Expected %TO not found in %DO statement.
ERROR: A dummy macro will be compiled

我是 SAS 和 stackoverflow 的新手,所以我希望我的问题不会太愚蠢。在 Python 和 R 中做到这一点非常简单,那么它必须有一种简单的方法在 SAS 中做到这一点。

感谢您的帮助 - J. Muller

4

2 回答 2

6

我在 SAS 宏语言中遇到过的最接近这种模式的是:

%MACRO test();

%let j=1;
%let vals=1 2 4 9;
%do %while(%scan(&vals,&j) ne );
  %let i=%scan(&vals, &j);

  %put &i;

  %let j=%eval(&j+1);
%end;
%MEND;

%test();

(警告:未经测试,因为我不再有 SAS 安装,我可以对其进行测试。)

于 2013-03-22T14:47:56.730 回答
4

你当然可以通过这种方式解决它:

options mindelimiter=,;
options minoperator;
%MACRO test();
  %DO i = 1 %to 9 ;
    %if &i in (1,2,4,9) %then %do;
    %PUT i = &i;
  %END;
  %end;
%MEND;

%test();

但是,我认为您通常可以通过多次执行宏而不是尝试控制宏内部的循环来避免这种调用。例如,想象一个数据集和一个宏:

data have;
input x;
datalines;
1
2
4
9
;;;;
run;

%macro test(x);
%put &x;
%mend test;

现在您想为该列表中的每个值调用一次 %test() 。好的,很容易做到。

proc sql;
select cats('%test(',x,')') into :testcall separated by ' ' from have;
quit;

&testcall;

这和你的 %do in loop 一样有效,除了它是数据驱动的,这意味着如果你想更改调用,你只需更改数据集(或者如果你的数据更改,调用会自动更改!)。一般来说,SAS 在设计为数据驱动编程而不是完全编写的代码时更有效。

于 2013-03-22T14:46:39.150 回答