The SAS Macro Facility


What is a Macro?

A SAS macro is way of defining parts of or collections of SAS statements which can be carried out repeatedly or which can substitute names of datasets and variables for symbolic names.

Say I want to do a set of linear regressions, and for each one get plots of the residual vs. predicted values. I can define a %reg macro like this:

%macro reg(data, y, x);
proc reg data=&data;
   model &y = &x;
        plot p. * r.;
%mend;
Then, I can use the %reg macro repeatedly, like this:
%reg(mydata, salary, educ);
%reg(mydata, salary, age);
%reg(mydata, salary, jobyears);

Positional macro arguments

Notice that the arguments to this macro are positional: The first one is substituted inside the macro statements whereever &data occurs; the second one is substituted whereever &y occurs, and so forth. This kind of macro is easy to use, but has the disadvantages that (a) you have to remember the order of the arguments, (b) you have to supply values for them all.

Keyword macro arguments

I could have defined the %reg macro like this, using keyword arguments:
%macro reg(data=_last_, y=, x=);
proc reg data=&data;
   model &y = &x;
        plot p. * r.;
%mend;
Note that the body of the macro (between %macro and %mend;) are identical. But now, I can call this macro with the arguments in any order:
%reg(data=mydata, y=salary, x=educ);
%reg(data=mydata, x=age, y=salary);
Note that the new definition of %reg includes a default value for the data argument: data=_last_. This means that if I omit the data= dataset name, SAS will use the "most recently created dataset", just like in all SAS procedures, so I could simply say,
%reg(y=salary, x=educ);
 

Conditional Macros

The SAS Macro Facility is much more general than this. Macros can be written to do a set of steps repeatedly, or to omit certain steps, depending on how they are called. The example below is just a hint at what can be done with macros. (The SAS Macro Facility is discussed in detail in chapter 20 of the SAS Language Reference.)

Here is a macro for a two-factor completely randomized design:

%macro anova2(data=_last_, resp=, A=, B=, plot=YES);
proc glm data=&data;            /* two-way analysis of variance */
   class &A &B;
   model &resp = &A | &B / ss3;
   lsmeans &A &B / stderr pdiff;
   lsmeans &A * &B / stderr pdiff out=lsm;
   output out=diag p=pred r=resid;
%if &plot=YES %then %do;
        proc plot data=lsm;             /* interaction plots */
                plot lsmean * &B = &A;
        proc plot data=diag;            /* diagnostic plots of pred vs. resid */
                plot resid * pred = &A;
                plot resid * pred = &B;
        %end;
%mend anova2;
Once this macros are defined, they can be used as follows. The second macro call will give the ANOVA results, but no plots.
%anova2(resp=height,A=age,B=gender);
%anova2(resp=height,A=age,B=gender, plot=NO);

Including External Macros

Macros and other SAS commands can be stored in an external file which can be included. For instance, suppose the two macros defined above were stored in a file called anova2.sas. The procedures section could be condensed to the following:
/* include previously defined macro */
%include 'c:\sas\sasuser\macros\anova2.sas';

%anova2(resp=height,A=age,B=gender);

Autocall Macro Libraries

One or more directories can be set up as "autocall macro libraries", which means that if a macro is invoked but has not yet been defined in your SAS session, SAS will search for a file with the macro name in each of the directories listed.

Autocall libraries are usually defined in the config.sas or autoexec.sas startup files. Here is the definition for the autocall libraries used on Pavlov:

/* SAS System autocall library definition     */

options SASAUTOS= (

              k:\home\sasuser\macros

              k:\home\sasuser\psy3030\macros

              k:\home\sasuser\psy6140\macros

              sasautos

          );

(The term sasautos at the end refers to the SAS-supplied standard autocall libraries.) 

Printing Macro Expansions

Macro expansions can be printed by turning on the mprint and msymbolgen options:
options ls=80 mprint msymbolgen;
This can be very handy to verify that macros are doing what they were designed to do.