Hi All,
I am trying to write a short macro for the regression model, where I need to create a string for the class variable for proc logistics. I have the following information:
%let Catvariable = Sex Race RUCC Treatment;
%let Reference = F W U P;
I want to create a string from the above information, which can be used in the class row of the proc logistics as follows:
Sex (ref = 'F') Race (ref= 'W') RUCC (ref='U') Treatment ('P');
I would greatly appreciate any thoughts.
Thanks,
sandyzman1
Seems simple enough, just use a %DO loop.
Let's try it by making a macro that takes those two inputs and emits the values.
%macro model(catvariable,reference);
%local i ;
%do i=1 %to %sysfunc(countw(&catvariable,%str( )));
%scan(&catvariable,&i,%str( )) (ref="%scan(&reference,&i,%str( ))")
%end;
%mend;
And let's try it with your example values:
8 %let string=%model(Catvariable = Sex Race RUCC Treatment,Reference = F W U P); 9 %put &=string; STRING=Sex (ref="F") Race (ref="W") RUCC (ref="U") Treatment (ref="P")
If you want to put the %DO loop in the middle of larger macro then just use a %LET statement in the middle of the %DO loop instead.
%do i=1 %to %sysfunc(countw(&catvariable,%str( )));
%let string=&string %scan(&catvariable,&i,%str( )) (ref="%scan(&reference,&i,%str( ))");
%end;
Seems simple enough, just use a %DO loop.
Let's try it by making a macro that takes those two inputs and emits the values.
%macro model(catvariable,reference);
%local i ;
%do i=1 %to %sysfunc(countw(&catvariable,%str( )));
%scan(&catvariable,&i,%str( )) (ref="%scan(&reference,&i,%str( ))")
%end;
%mend;
And let's try it with your example values:
8 %let string=%model(Catvariable = Sex Race RUCC Treatment,Reference = F W U P); 9 %put &=string; STRING=Sex (ref="F") Race (ref="W") RUCC (ref="U") Treatment (ref="P")
If you want to put the %DO loop in the middle of larger macro then just use a %LET statement in the middle of the %DO loop instead.
%do i=1 %to %sysfunc(countw(&catvariable,%str( )));
%let string=&string %scan(&catvariable,&i,%str( )) (ref="%scan(&reference,&i,%str( ))");
%end;
Hi @Tom,
Thank you so much for the macro. It worked perfectly. However, as you suggested, when I use the %DO loop (below) in the middle of a larger macro using a %LET statement.
%do i=1 %to %sysfunc(countw(&catvariable,%str( )));
%let string=&string %scan(&catvariable,&i,%str( )) (ref="%scan(&reference,&i,%str( ))");
%end;
It gave me the following error.
WARNING: Apparent symbolic reference STRING not resolved.
ERROR: The text expression &STRING. SEX (REF="F") contains a recursive reference to the macro variable
STRING. The macro variable will be assigned the null value.
Do you have any suggestions? Thanks.
Add
%local string;
to your macro before the %DO loop.
It defines the macro variable, and avoids unpleasant side-effects.
Make sure STRING is defined BEFORE trying to reference its value.
So either set it to an empty string before the %DO loop.
%let string=;
Or define it as a LOCAL macro variable (which will also start as empty.)
%local string;
Or you might want to do both, depending on whether you want to reuse STRING multiple times in the macro code.
Parallel lists are hard to manage. I suggest using a lookup object. In this case an INFORMAT.
%macro
main
(
Catvariable = Sex Race RUCC Treatment,
Reference = RACE=W RUCC=U TREATMENT=P SEX=F ABC=2 XYZ=1
);
proc format;
invalue $ref(upcase just) &reference;
run;
%local i w;
%do i = 1 %to %sysfunc(countw(%superq(catvariable)));
%let w = %scan(%superq(catvariable),&i);
%put NOTE: CLASS &w(ref=%sysfunc(inputc(&w,$ref),$quote.));
%end;
%mend main;
%main;
NOTE: CLASS Sex(ref="F" ) NOTE: CLASS Race(ref="W" ) NOTE: CLASS RUCC(ref="U" ) NOTE: CLASS Treatment(ref="P" )
I would probably define the INFORMAT outside the MACRO but you get the idea. It would be helpful to know the big picture.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.