BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
sandyzman1
Obsidian | Level 7

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

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

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;

View solution in original post

5 REPLIES 5
Tom
Super User Tom
Super User

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;
sandyzman1
Obsidian | Level 7

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.

Tom
Super User Tom
Super User

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.

 

data_null__
Jade | Level 19

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: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 874 views
  • 6 likes
  • 4 in conversation