Sandra Guerrero
Sandra Guerrero

Reputation: 323

The drop sentence doesn't work with variables created with macro arrays SAS

I am trying to run the following code, that calculates the slope of each variables' timeseries. I need to drop the variables created with an array, because I use the same logic for other functions. Nevertheless the output data keeps the variables ys_new&i._: and I get the warning: The variable 'ys_new3_:'n in the DROP, KEEP, or RENAME list has never been referenced. I think the iterator is evaluated to 3 in the %do %while block. If someone can help me, I will really apreciated it.

DATA HAVE;
INPUT ID N_TRX_M0-N_TRX_M12 TRANSACTION_AMT_M0-TRANSACTION_AMT_M12;
DATALINES;
1 3 6 3 3 7 8 6 10 5 5 8 7 7 379866 856839 307909 239980 767545 511806 603781 948936 566114 402214 844657 2197164 817390
2 51 56 55 73 48 57 54 53 55 52 49 72 53 6439314 7367157 4614827 9465017 3776064 3661525 7870605 3971889 4919128 10024385 4660264 7748467 7339863
3 5 . . . . . . . . . . . . 232165 . . . . . . . . . . . .
;
RUN;

%Macro slope(variables)/parmbuff;
    %let i = 1;
    /* Get  the  first  Parameter */
    %let parm_&i = %scan(&syspbuff,&i,%str( %(, %)));
    
    %do %while (%str(&&parm_&i.) ne %str());

        array ys&i(12) &&parm_&i.._M12 - &&parm_&i.._M1;
        array ys_new&i._[12];
        
/*      Corre los valores missing*/
        k = 1;
        do j = 1 to 12;
            if not(missing(ys&i(j))) then do;
                ys_new&i._[k] = ys&i[j];
                k + 1;
            end;
        end;

        nonmissing = n(of ys_new&i._{*});

        xbar = (nonmissing + 1)/2;

        if nonmissing ge 2 then do;                     
            ybar = mean(of ys&i(*));
            
            cov = 0;
            varx = 0;

            do m=1 to nonmissing;
                cov=sum(cov, (m-xbar)*(ys_new&i._(m)-ybar));
                varx=sum(varx, (m-xbar)**2);
            end;

            slope_&&parm_&i. = cov/varx;
        end;            
        %let i = %eval(&i+1);
    /* Get  next  parm */
    %let  parm_&i =  %scan(&syspbuff ,&i, %str( %(, %)));
    %end;
    drop ys_new&i._: k j m nonmissing ybar xbar cov varx;
%mend;

%let var_slope = 
    N_TRX,
    TRANSACTION_AMT
;

DATA FEATURES;
    SET HAVE;
    %slope(&var_slope)
RUN;

Upvotes: 1

Views: 144

Answers (2)

Tom
Tom

Reputation: 51621

The simplest solution is to generate the DROP statement before the macro has a chance to change the value of the macro variable I .

array ys&i(12) &&parm_&i.._M12 - &&parm_&i.._M1;
array ys_new&i._[12];
drop ys_new&i._: k j m nonmissing ybar xbar cov varx;

You could use a _TEMPORARY_ array instead, but then you need to remember to clear the values on each iteration of the data step.

array ys_new&i._[12] _temporary_;
call missing(of ys_new&i._[*]);

Then you can leave the DROP statement at the end if you want.

drop k j m nonmissing ybar xbar cov varx;

Upvotes: 2

Stu Sztukowski
Stu Sztukowski

Reputation: 12934

You are correct. &i is 3 after it exits the do loop leading to the drop statement giving a warning that ys_new3_: does not exist. Instead, consider using a temporary array to avoid the drop statement altogether:

array ys_new&i._[12] _TEMPORARY_;

Upvotes: 0

Related Questions