I'm working with SAS and I have to create some macro variables within a DO loop. This is a portion of my code:
%if &dsempty888=0 %then %do;
data _null_;
set freq_&&var&i;
if &&var&i=888888888 then do;
call symput("cont8_&&var&i",percent);
end;
run;
%end;
%if &dsempty888=1 %then %do;
%let cont8_&&var&i=0;
%end;
%if &dsempty999=0 %then %do;
data _null_;
set freq_&&var&i;
if &&var&i=999999999 then do;
call symput("cont9_&&var&i",percent);
end;
run;
%end;
%if &dsempty999=1 %then %do;
%let cont9_&&var&i=0;
%end;
%if &dsempty444=0 %then %do;
data _null_;
set freq_&&var&i;
if &&var&i=444444444 then do;
call symput("cont4_&&var&i",percent);
end;
run;
%end;
%if &dsempty444=1 %then %do;
%let cont4_&&var&i=0;
%end;
This code is inside another DO loop that run from i=1 to &end
. With this my macro variables cont4_&&var&i
cont8_&&var&i
cont9_&&var&i
are costantly overwrited...and they become unuseful outside of their loop. I tried to name them &&cont4_&&var&i
for example. But clearly SAS doesn't solve the macro. In practice inside of the loop the macro are created, but I don't know how to call them when I need outside.
How can I fix?
Thanks in advance.
You've got a lot of issues here, so let's simplify this some. Here's a very simplified example. This, for example, does something:
%let var1 = age;
%let var2 = height;
%let var3 = weight;
proc freq data=sashelp.class noprint;
tables age/out=freq_age;
tables height/out=freq_height;
tables weight/out=freq_weight;
run;
%macro get_freqs(var_count=);
%do i = 1 %to &var_count.;
data _null_;
set freq_&&var&i;
call symput("cont4_&&var&i",percent);
run;
%end;
%mend get_freqs;
%get_Freqs(var_count=3)
But now if we do
%put cont4_&&var&i;
Of course it doesn't work, since &i
has no meaning. So instead we replace that with, say, 1:
%put cont4_&&var1;
Now we get something. But we don't get anything useful, do we, just the variable name. But - at least that's something!
Now we don't really need the second &
there, right?
%put cont4_&var1;
But we need a &
before this to use the macro variable:
%put &cont4_&var1;
But now we get a warning message, CONT4_ not resolved
. Okay, let's add a second &
to delay the resolution of the macro variable until &var1
is resolved.
%put &cont4_&var1;
Well, that helped, now it says CONT4_AGE not resolved
. Why not? We used call symput
to define that, right?
The problem is scoping . call symput
probably scoped it locally, meaning it was defined in the macro but not outside of the macro. For this we use call symputx
and give it a global scope.
%macro get_freqs(var_count=);
%do i = 1 %to &var_count.;
data _null_;
set freq_&&var&i;
call symputx("cont4_&&var&i",percent,'g');
run;
%end;
%mend get_freqs;
This tells SAS that I want &cont4_age
to be defined outside of the macro. Otherwise it will only be available locally - inside the macro - and will get cleaned up.
Now, this works:
%put &&cont4_&var1;
But if you wanted to iterate over &i
again, it's a bit more complex. That's because you need to delay those ampersands multiple times, and allow several passes.
Here's what works:
%macro iterate_i(var_count=);
%do i = 1 %to &var_count.;
%put &&&&cont4_&&var&i.;
%end;
%mend iterate_i;
%iterate_i(var_count=3);
Why do we need four &
s? Well, we need to get to &&cont4_&var1
, right? That happens in the first pass. Here are the three passes:
&&&&cont4_&&var&i
-> &&cont4_&var1
-> &cont4_age
-> 5.26...
Each pass, the following happens:
&&
-> &
(and save for next pass) &
-> resolve macro variable So, that's how you'd iterate over those. You can of course explicitly specify at any level the macro variable - so all of these work:
%let i=1;
%put &&&&cont4_&&var&i;
%put &&cont4_&var1;
%put &cont4_age;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.