Question

i am wanted to create following data-sets, P1_31,P1_32,P1_36,P1_37 in SAS using following code

%MACRO P_MISS1;
%LET T1= 3 ;
%LET H1=1;
%DO %WHILE(&H1<=1);
        %LET TR1=%SCAN(&T1,&H1);
            %DO I= 1,2,6 %TO 7;
                DATA P1_&TR1&I;
                    VALUE=.;
                    COL&TR1=.;
                RUN;
                OUTPUT;
            %END;
     %LET H1=%EVAL(&H1+1);
 %END;
%MEND P_MISS1;

%P_MISS1

i used many macro program to all those above data-sets, but just to reduce the code size i was creating the following code. i know i am doing something wrong with %Do Loop. Please guide me with the code, if there is any possibility to use above code.

Was it helpful?

Solution

The better way to write this sort of code, just like any programming language, is to write the macro as the piece you want to run multiple times, and then call it multiple times. That makes it more reusable, makes more clear what you're doing, and ultimately ends up with shorter code much of the time.

This particular set of code it's not entirely obvious how the best way to write it would be, because the things driving your inputs aren't obvious. However, something like this would make sense.

%macro make_ds(tr,i);
DATA P1_&TR1&I;
  VALUE=.;
  COL&TR1=.;
RUN;
%mend make_ds;

%macro call_make_ds(tr);
  %make_ds(&tr,1);
  %make_ds(&tr,2);
  %make_ds(&tr,6);
  %make_ds(&tr,7);
%mend call_make_ds;

For four items I'd just write them out, if there's no dataset or other entity that contains the four items. It's just as much code frankly to write the complex loop, more error prone, and not really much easier to maintain. If you have a dataset that contains the possible values for i, then use that to call the %make_ds macro.

Then call that macro based on the appropriate parameters. For example, if TR can be determined from a dataset (say you have a dataset that contains all TR values you want to iterate over), you could do something like this:

proc sql;
select distinct cats('%call_make_ds(',trval,')') into :makelist 
 separated by ' ' 
 from your_ds;
quit;
&makelist;

OTHER TIPS

Well, this line is wrong as far as my SAS knowledge goes:

%DO I= 1,2,6 %TO 7;

Normally, you write:

%do macrovar=startvalue %to endvalue;

I would propose that you create a macro with a list of items you want to use as suffix and loop over them:

%MACRO P_MISS1;
    %let suffixes=31 32 36 37;
    %let elementNbr=1;
    %let elementValue=%scan(&suffixes.,&elementNbr.); /*initiate with first element*/

    %do %while(&elementValue. NE %str()); /*as long as we find elements, we continue iterating*/
        data P1_&elementValue.;
            value=.;
            col3=.;
            output;
        run;
        %let elementNbr=%eval(&elementNbr.+1); /*increase elementNbr, so that we look now for the next item in our list*/
        %let elementValue=%scan(&suffixes.,&elementNbr.); /*initiate next element*/
    %end;
%mend;
%P_MISS1

You seem to have something going with 2 levels: multiples of 10 and units. I skipped that nuance in the code above, but you can implement it by nesting such loops.
E.g., the outer loop loops over the multiples of 10 (in your case, that is only the 3 of nbr 30) and the inner loop over the values you want there (in your case: 1, 2, 6 and 7)

All that being said, i seem to miss the point of your code. You are creating empty datasets, but to what purpose? Are you certain that you need to have those in your scenario?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top