DATA Step, Macro, Functions and more

Macro Variable Scope

Reply
Frequent Contributor
Posts: 97

Macro Variable Scope

I am trying to write a macro to run through a list of variables and calculate descriptive statistics. I have run into a problem, I think with variable scope, that I can't get past, and I would greatly appreciate any help. The problem boils down to this:

%MACRO TEST();
DATA _NULL_;
%LET I = 1;
DO INC=1 TO 3;
%LET I = %EVAL(&I + 1);
PUT "&I";
END;
RUN;
%MEND;
%TEST();

This generates 2, 2, 2 rather than 2, 3, 4.

The full code I am trying to use, if that helps, is this:

%MACRO DATAINFO(DATA, VARS);
DATA _NULL_;
%LET FILENAME = "&SASDATA.MACROS\PRG.SAS";
FILE &FILENAME;
%LET VAR = %SYSFUNC(SCAN(%QUOTE(&VARS), 1));
PUT "PROC SQL;";
PUT "SELECT "; PUT """&VAR"""; PUT " AS VAR,";
PUT "COUNT(&VAR) LABEL='Total of Obs',";
PUT "COUNT(DISTINCT &VAR) LABEL='Unique Values',";
PUT "FROM &DATA";
PUT "GROUP BY VAR";
%LET COUNT = %SYSFUNC(COUNTW(%QUOTE(&VARS)));
IF &COUNT > 1 THEN DO;
%LET I = 1;
DO INC=2 TO &COUNT;
%LET I = %EVAL(&I + 1);
%PUT &I;
%LET VAR = %SYSFUNC(SCAN(%QUOTE(&VARS), &I));
PUT "UNION";
PUT "SELECT "; PUT """&VAR"""; PUT " AS VAR,";
PUT "COUNT(&VAR) LABEL='Total of Obs',";
PUT "COUNT(DISTINCT &VAR) LABEL='Unique Values',";
PUT "FROM &DATA";
PUT "GROUP BY VAR";
END;
END;
PUT ";QUIT;";
RUN;
*%INCLUDE &FILENAME;
%MEND;

/*USAGE*/
/*
%LET INITIAL = AGE HAZARD_GROUP CLASSCOUNT;
%DATAINFO(MODEL.DATA, &INITIAL);
*/

The problem is, whether I try to use I or INC, I can't get a variable to increment in this line:

%LET VAR = %SYSFUNC(SCAN(%QUOTE(&VARS), &I));

If I use INC, it says this is not numeric. If I use I, I can't get it to increment. I would appreciate ANY suggestions.

Thanks,
Chris
Christopher Johnson
www.codeitmagazine.com
Respected Advisor
Posts: 3,777

Re: Macro Variable Scope

I can't say I understand what you are trying to do here but when I look at your program I think, PROC MEANS.

PROC MEANS can process MANY variables at one time so no looping over lists of variables is necessary. Plus the syntax is designed to calculate many stats with little effort and the CLASS statement allows many WAYS of grouping.
Regular Contributor
Posts: 241

Re: Macro Variable Scope

The reason for the problem boils down to your macro %test generating the following code (as reported on log by turning on the mprint option):
[pre]
MPRINT(TEST): DATA _NULL_;
MPRINT(TEST): DO INC=1 TO 3;
MPRINT(TEST): PUT "2";
MPRINT(TEST): END;
MPRINT(TEST): RUN;
[/pre]

If you really want to return 2, 3, 4, then your macro should be something like:
[pre]
%macro count(from=2, to=4);
%local i;
%do i = &from %to &to;
%if &i > &from %then %*;,;
%*;&i
%end;
%mend count;

%put %count(to=4);
%*-- on log
2,3,4
--*;
[/pre]
This may be too advance for you, but just in case, looping over a list of blank delimited words is such a common task that there have been much development in making it simple. For instance, you can separate the looping part out into a separate macro so that you can do something like this one posted on the sas-l:
http://www.listserv.uga.edu/cgi-bin/wa?A2=ind1011a&L=sas-l&O=D&P=999
SAS Employee
Posts: 58

Re: Macro Variable Scope

Yes, do something similar to what Chang said, or just change yours as follows:

%MACRO TEST();
DATA _NULL_;
%DO i=1 %TO 3;
%LET J = %EVAL(&I + 1);
PUT "&J";
%end;
RUN;
%MEND;
%TEST();
Ask a Question
Discussion stats
  • 3 replies
  • 136 views
  • 0 likes
  • 4 in conversation