包含 proc 或数据步骤的宏在数据步骤内不可执行。宏不是函数或子程序;它们是文本,就像您输入它一样(只是通过循环和条件节省了一些时间)。因此,您的宏的内容需要是可以在数据步骤中执行的文本:
%macro mymacro(numiters);
*this macro would be easier to do in an array, but it is an example;
%local t;
%do t = 1 to &numiters.;
x&t. = mean(y&t.,z&t.);
%end;
%mend mymacro;
data output;
set input;
%mymacro(5);
run;
在这种情况下,不将值存储在宏变量中会更容易(并且在风格上更正确)。只需将结果包含在数据步骤变量中,并在需要时将该变量的名称作为参数之一传递。
还有一些函数样式的宏,它们实际上将一个值返回给数据步骤(或者在这种情况下,返回等同于一个值的文本)。它们可以用在等号的右边。
%macro xtothey(in,power);
%local t;
&in.
%do t = 1 to &power-1;
*&in.
%end;
;
%mend myfunctionmacro;
data output;
set input;
y = %xtothey(x,4);
run;
这实际上在 PROC FCMP(编译函数和子例程)中更容易完成,但有时宏对此更好(或者您可能不太了解 FCMP)。
最后,一些宏需要它们自己的过程或数据步骤。在这些情况下,除非您使用某些 FCMP 元素,例如 DOSUBL,否则您需要将值存储在某个地方,无论是在数据集还是宏中。在这些情况下,您必须在需要值的数据步之前运行宏 - 但您只能获得一个(或有限数量的)返回值。除非你达到一些极端的长度,否则你不会每行得到一个,这通常可以在不使用宏变量的情况下做得更好。我认为下面的形式不好,因为你几乎总是可以在不使用宏变量的情况下做得更好——但如果你需要,这就是你会这样做的方式。带有 DOSUBL 的 FCMP 可能是更好的选择。
%macro findmode(dset,var,outvar);
proc means data=&dset;
var &var.;
output out=_tempset mode(&var.)=&var._mode;
run;
data _null_;
set _tempset;
call symputx("&outvar.",&var._mode);
run;
%mend findmode;
%findmode(sashelp.class,weight,wtmode);
data output;
set input;
mode=&wtmode;
run;