BookmarkSubscribeRSS Feed
cjohnson
Obsidian | Level 7
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
3 REPLIES 3
data_null__
Jade | Level 19
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.
chang_y_chung_hotmail_com
Obsidian | Level 7
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
PatrickG
SAS Employee
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();

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 701 views
  • 0 likes
  • 4 in conversation