Good morning. I have defined variable names in %let statements, but am having trouble trying to resolve part that cycles through a %do loop. Here is the simplified version:
%let vars=%nrstr(var&n._x var&n._y);
%macro datapull;
data want;
set have;
keep %do n=1 %to 10; &vars %end;;
run;
%mend;
The macro runs fine if I substitute in all of the variable names by hand - meaning entering each variation 10 times. I've tried using different forms of %nrstr, %superq, etc, but just can't figure this one out. Do I need to define the %let statement in it's own macro? I've also tried putting the %do n1-10 %end statement in the %let statement as well. I feel like I'm missing something easy here. What is it?
I'd like to keep this format - I know the obvious way is to just type out all the variable names.
Hello @JenniferBernard,
The %NRSTR function avoids the warning about &n not being resolved by adding invisible macro quoting characters to the macro variable value. To get rid of these added characters in the %DO loop, where they would cause errors, use the %UNQUOTE function:
keep %do n=1 %to 10; %unquote(&vars) %end;;
If those variables in the KEEP statement are contained in dataset HAVE, you may want to replace the KEEP statement with a KEEP= dataset option to improve performance:
set have(keep=%do n=1 %to 10; %unquote(&vars) %end;);
Okay, I've seemed to resolve this by just having
%let vars=var&n._x var&n._y;
The macro works and completes, but the log gives the warning that the reference isn't resolved. I think this might be okay?
@JenniferBernard wrote:
Okay, I've seemed to resolve this by just having
%let vars=var&n._x var&n._y;
The macro works and completes, but the log gives the warning that the reference isn't resolved. I think this might be okay?
It doesn't sound okay to me. Can you run this command before you run the macro,
options mprint;
then run the macro again and show us the ENTIRE log for the macro (all of it, do not pick and choose parts of the log to show us).
The warning comes from the &n. not being resolved in the let statement (outside the macro).
I checked with mprint and it did indeed resolve to include all of my variables.
Adding:
naming variables like var1_x var1_y var2_x var2_y and so on makes your programming more difficult. If, on the other hand you had named your variables varx_1 vary_1 varx_2 vary_2 then your programming is much easier.
Your KEEP statement can then be reduced to
keep varx_1-varx_10 vary_1-vary_10;
or even simpler (if appropriate)
keep varx: vary:;
no macros needed
Yes, 100% agree. Can't do anything with this set-up however.
Best solution is to go back to the drawing board and make sure to place the numeric sequence at the END of the variable names. Then you can skip any need for code generation.
Sounds like you need a macro tool that takes three inputs.
%macro varlist(base,count,suffix);
%local i j ;
%do i=1 %to &count;
%do j=1 %to %sysfunc(countw(&suffix,%str( )));
&base.&i%scan(&suffix,&j,%str( ))
%end;
%end;
%mend ;
Example:
400 %put %varlist(var,10,_x _y); var1_x var1_y var2_x var2_y var3_x var3_y var4_x var4_y var5_x var5_y var6_x var6_y var7_x var7_y var8_x var8_y var9_x var9_y var10_x var10_y
Note if you are using this inside of a macro you might need to add something to prevent the parser from getting confused by the macro function call in the middle of the variable name. So something like:
%macro varlist(base,count,suffix);
%local i j ;
%do i=1 %to &count;
%do j=1 %to %sysfunc(countw(&suffix,%str( )));
%unquote(&base.&i%scan(&suffix,&j,%str( )))
%end;
%end;
%mend ;
Hello @JenniferBernard,
The %NRSTR function avoids the warning about &n not being resolved by adding invisible macro quoting characters to the macro variable value. To get rid of these added characters in the %DO loop, where they would cause errors, use the %UNQUOTE function:
keep %do n=1 %to 10; %unquote(&vars) %end;;
If those variables in the KEEP statement are contained in dataset HAVE, you may want to replace the KEEP statement with a KEEP= dataset option to improve performance:
set have(keep=%do n=1 %to 10; %unquote(&vars) %end;);
Here is a way to see what values you are currently creating:
%let vars=%nrstr(var&n._x var&n._y); %macro dummy; %do n=1 %to 10; %put resolved variables: &vars ; %end; %mend; %dummy;
And what may be one way to create what you are expecting:
%macro dummy2(vars=var&n._x var&n._y); %do n=1 %to 10; %put resolved variables: &vars ; %end; %mend; %dummy2;
Note since I am using the %put statement it does need the ; to end the statement. If you want/need a single Keep statement then your current structure would work while passing the parameter this way. Or create multiple Keep statements. Since you are not using a data set option multiple keeps will work:
data junk; set sashelp.class; keep name; keep age; run;
I am not a fan of just letting a macro parameter, your Vars variable, just appear in the middle of a macro. It is often hard to tell just when a value is assigned or used and debugging scope problems gets much more difficult.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.