Giacomo Rosaspina
Giacomo Rosaspina

Reputation: 111

How to use the && macro variable in SAS

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.

Upvotes: 0

Views: 4588

Answers (1)

Joe
Joe

Reputation: 63424

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;

Upvotes: 4

Related Questions