Search code examples
arrayssassas-macro

SAS: improve efficiency of array with macros


I'm trying to practice SAS macros at the moment, and while they seem logical for the most part, I've found little information in the documentation about how to improve the efficiency of an array with macros. Is there a different way and I'm doing all this all wrong? I'd like to improve some SAS code at work so this is just a simple example which I learn how to do it.

Here is my original basic array code:

data dataset_new;    
    set dataset_old;
    array array_one{12} value01-value12;
    do i = 1 to 12;  
        if array_one{i} = '121' then sponsor = 'yes';
        if array_one{i} in ('44', '55')  then participant = 'active';
    end;         
run;        

And here is my lame attempt at trying to add macros into this.

%let maximum = 10;   
%MACRO SPORTS(START,maximum);
data dataset_new;    
    set dataset_old;
    array array_one{12} value01-value12;
    %DO i = &START %TO &maximum ;
        if array_one{i} = '121' then sponsor = 'yes';
        if array_one{i} in ('44', '55')  then participant = 'active';
    %END;        
%MEND SPORTS;        
run;        

Thanks for any thoughts on how to do this.


Solution

  • You are mixing scope, which is often not desirable.

    What is the so-called improvement you seem to be wanting ?

    The %do loop will generate source code for 2 data step if statements for each iteration of the macro %do.

    The global maximum assignment outside the macro does nothing in regards to setting or overriding the maximum that the macro invocation should be passing. The macro SPORTS has to be invoked for anything to happen, otherwise you are simply compiling a macro. The macro definition is also weirdly interleaved with the run; outside the macro definition. In gentle, you are doing it all wrong.

    Macro generates source code, and thus can not alter the source code of a running (and thus already been compiled data step)

    At a theoretical minimum, you might want

    if array_one{&i} = '121' then sponsor = 'yes';
    

    instead of

     if array_one{i} = '121' then sponsor = 'yes';
    

    but that really doesn't do help in a broader sense.

    Are you actually try to evaluate the difference between

    do i = 1 to 12;  
        if array_one{i} = '121' then sponsor = 'yes';
        if array_one{i} in ('44', '55')  then participant = 'active';
    end;
    

    and macro generated source

        if value01 = '121' then sponsor = 'yes';
        if value01 in ('44', '55')  then participant = 'active';
        if value02 = '121' then sponsor = 'yes';
        if value02 in ('44', '55')  then participant = 'active';
        if value03 = '121' then sponsor = 'yes';
        if value03 in ('44', '55')  then participant = 'active';
        if value04 = '121' then sponsor = 'yes';
        if value04 in ('44', '55')  then participant = 'active';
        if value05 = '121' then sponsor = 'yes';
        if value05 in ('44', '55')  then participant = 'active';
        if value06 = '121' then sponsor = 'yes';
        if value06 in ('44', '55')  then participant = 'active';
        if value07 = '121' then sponsor = 'yes';
        if value07 in ('44', '55')  then participant = 'active';
        if value08 = '121' then sponsor = 'yes';
        if value08 in ('44', '55')  then participant = 'active';
        if value09 = '121' then sponsor = 'yes';
        if value09 in ('44', '55')  then participant = 'active';
        if value10 = '121' then sponsor = 'yes';
        if value10 in ('44', '55')  then participant = 'active';
        if value11 = '121' then sponsor = 'yes';
        if value11 in ('44', '55')  then participant = 'active';
        if value12 = '121' then sponsor = 'yes';
        if value12 in ('44', '55')  then participant = 'active';