SUPPORT / SAMPLES & SAS NOTES
 

Support

Sample 66249: RunBY macro: Repeatedly run or add BY processing to any macro, procedure, or special code

DetailsResultsDownloadsAboutRate It

RunBY macro: Repeatedly run or add BY processing to any macro, procedure, or special code

Contents: Purpose / History / Requirements / Usage / Details / Limitations / Missing Values / See Also
PURPOSE:
Many macros, and some procedures, were not written with the built-in capability to perform their analysis or operation separately on each of multiple blocks of observations in the input data set. For example, if your data set contains a block of observations for each of several countries or regions or conditions (such as gender or race), most SAS procedures allow you to run the procedure a single time with a BY statement telling the procedure to do the analysis or operation on each block of observations (called BY groups). The RunBY macro makes it possible to do the same with most macros and procedures that do not have this built-in BY processing capability. More generally, the macro can be used to run any code as indicated by the contents of each observation in a specified data set.
HISTORY:
The version of the RunBY macro that you are using is displayed when you specify version (or any string) as the first argument. For example:
    %RunBY(version)

The RunBY macro always attempts to check for a later version of itself. If it is unable to do this (such as if there is no active internet connection available), the macro will issue the following message:

   NOTE: Unable to check for newer version

The computations performed by the macro are not affected by the appearance of this message.

Version
Update Notes
1.1 Added lvlquote= and print=
1.0 Initial coding
REQUIREMENTS:
Only Base SAS® is required.
USAGE:
Follow the instructions on the Downloads tab of this sample to save the RunBY macro definition. Replace the text within quotation marks in the following statement with the location of the RunBY macro definition file on your system. In your SAS program or in the SAS editor window, specify this statement to define the RunBY macro and make it available for use:
   %inc "<location of your file containing the RunBY macro>";

After running the above statement, the RunBY macro is ready for use. However, before you call the macro, you must create a simple macro, named code, that contains the code that you want to apply to each BY group. See Details below and the Results tab for examples.

The following parameter is required when using the RunBY macro:

by=variable(s)
List the variables that define the BY groups. Variables can be numeric or character. None of the values in character variables can contain the percent (%) or ampersand (&) character or contain unmatched quotation marks (' or "). A BY group is one combination of values of all of the variables specified in by=.

The following parameters are optional:

data=data-set-name
Specify the name of a data set that contains the by= variables with the desired levels defining all BY groups. The code that you supply in the code macro will be run once for each BY group defined by the by= variables in this data set. This data set might or might not be the data set that is analyzed by the code that you supply in the CODE macro. If data= is not specified, then the last created data set is used.
order=internal|formatted|data|freq
Specifies how the by= variable values should be ordered. internal uses the unformatted variable values. formatted uses the formatted variable values if a format is assigned. data orders the values as they are in the data= data set. freq orders the values in decreasing frequency as found in the data= data set. The order of the by= variable values in the data= data set do not have to be in the order specified in order= unless order=data is specified.  The default is order=internal.
lvlquote=yes|no
Values of character by= variables, represented by the _LVL macro variables, can be inserted into the supplied code with surrounding double quotation marks (lvlquote=yes) or without quotation marks (lvlquote=no), depending on what is needed in the supplied code. See the Example in Details below. The default is lvlquote=yes.
print=yes|no
Displayed results produced from running the supplied code can be displayed (print=yes) or suppressed (print=no). The default is print=yes.
DETAILS:
The RunBY macro runs the code that you supply once for each BY group as defined by the combinations of the by= variable values found in the data= data set. For example, if you specify by=gender, then the code is run once for males and once for females. Unlike with the BY statement used in the DATA step or procedures, it is not necessary to sort the data= data set by the by= variables before using the RunBY macro.
 

User-defined macro, code, and special macro variables _BYx, _LVLx, and _BYlabel

You specify the code that you want to run on each BY group in a simple macro called code. In order for your code to select one BY group at a time, it should contain a subsetting condition using a special pair of macro variables, _BYx and _LVLx, where x is a number representing the x-th variable specified in by=. Typically, your code will do this by containing a WHERE statement or clause that uses these macro variables. If a by= variable is character, it is not necessary to specify quotation marks around _LVLin the condition. Additionally, the macro variable, BYlabel, is available for labeling the displayed results with the BY group definition. BYlabel can be used in a TITLE, FOOTNOTE, or other appropriate statement or option.

Example

Following is an example where the BY groups are defined by the single character variable, Gender, that has values Female and Male in data set MyData. You want to run a macro (not shown) called MyMacro for each level of Gender. You precede your code with a %macro code(); statement, and follow it with a %mend; statement as shown. Assuming that MyMacro does not have built-in BY processing capabilities, an analysis on one Gender level needs to subset the data and then run MyMacro on that subset. The subsetting is easily done with a WHERE statement in a DATA step to create the subset. A WHERE clause in the SET statement could be used instead. When the RunBY macro runs, it replaces the macro variables, _BY1 and _LVL1, with Gender="Female" for one analysis, and then with Gender="Male" for the second analysis. Note that you do not need to specify quotation marks around _LVL1 in the WHERE statement condition since this is done for you by lvlquote=yes. The results are labeled with a title line showing the appropriate one of these two BY group definitions. This assumes that MyMacro itself does not overwrite any prior title. If so, perhaps a FOOTNOTE statement could be used instead. Note the use of the ampersand (&) character to allow resolution of the _BY1, _LVL1, and BYlabel macro variables.

    %macro code();
      data subset;
        set MyData;
        where &_BY1 = &_LVL1;
        run;
      title "&BYlabel";
      %MyMacro(data=subset)
      title;
    %mend;
    %RunBY(data=MyFullData, by=Gender)

If MyMacro is written to accept data set options in its data= parameter, the following could also work:

    %macro code();
      %MyMacro( data=subset(where=(&_BY1 = &_LVL1)) )
    %mend;
    %RunBY(data=MyData, by=Gender)

If there are multiple by= variables, for example by=gender race, then the WHERE statement would include a second condition as below, and so on, for any number of by= variables.

    where &_BY1 = &_LVL1 and &_BY2 = &_LVL2;
LIMITATIONS:
Unmatched quotation marks, either an unmatched single quotation mark (') or an unmatched double quotation mark ("), and the ampersand (&) and percent (%) characters are not allowed in the values of any of the by= variables and might cause errors. If ampersand (&) and percent (%) characters are detected, a WARNING message is printed in the log and the BY group is skipped.
MISSING VALUES:
Missing values in the by= variables are treated as additional levels.
SEE ALSO:
Another way to run macros, procedures, or special code is using the CALL EXECUTE function in the DATA step. This method is shown in SAS Note 46847 to fit a series of logistic models using, in turn, one variable from a set of predictor variables.



These sample files and code examples are provided by SAS Institute Inc. "as is" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and fitness for a particular purpose. Recipients acknowledge and agree that SAS Institute shall not be liable for any damages whatsoever arising out of their use of this material. In addition, SAS Institute will provide no support for the materials contained herein.