Search code examples
sassas-macro

SAS How to create multiple variables with date suffix in a do loop


I'm trying to create multiple variables based on conditions with date as their suffix. The following code only generate one variable from the end date. How do I make it generate multiple variables based on dates in between the end and start date, and keep them on master2?

%macro dis_status(startdate,enddate);
%let sasstart = %sysfunc(inputn(%substr(&startdate,3,6),yymmdd6.));
%put &sasstart;
%let sasend = %sysfunc(inputn(%substr(&enddate,3,6),yymmdd6.));
%put &sasend;

%do sasdate=&sasstart %to &sasend;
    %let date= %sysfunc(putn(&sasdate,yymmdd6.));
    %put &date;

     data master2;
       set master1;
        if code22_&date. in ('1','2','3','4') 
                then status22_&date. = "G "; 
        else if CODE22_&date. in ('5','6') 
                                         then status22_&date. = "IE"; 
        else if CODE22_&date. in ('7','8') 
                then status22_&date. = "NR"; 
        else CODE22_&date. in ('10,'11')
                then status22_&date. = "UE"; 
       run;
%end;
%mend;

%dis_status(20220608,20221019);

Solution

  • Use the macro code with in the DATA Step source to generate the statements you want.

    Data provided in a very wide layout with date representation as part of the variable name is typically problematic in the long run. Consider pivoting the data so the date is a column. Such a table can be processed efficiently with WHERE

    Wide Example:

    This presumes the data set have has many variables named CODE22_yymmdd and many new variables named status22_yymmdd are to be computed. Macro code is used to create source code for initializing arrays. A custom format is used to perform the transformation from code to status.

    * mock up some wide data;
    data have;
      call streaminit(20230221);
      do id = 1 to 100;
        length code22_230101-code22_230131 code22_230201-code22_230228 $2;
        array code22 code22_:;
        do over code22;
          code22 = put(rand('integer',1,12),2.-L);
        end;
        output;
      end;
    run;
    
    proc format;
      value $code_to_status (default=2)
        '1','2','3','4' = 'G '
        '5','6' = 'IE'
        '7','8' = 'NR'
        '10','11' = 'UE'
      ;
    run;
    
    %macro example(from, to);
    
      %local from_date to_date date yymmdd;
    
      %let from_date = %sysfunc(inputn(&from,yymmdd8.));
      %let to_date   = %sysfunc(inputn(&to,yymmdd8.));
    
      data want;
        set have;
        array code22 %do date=&from_date %to &to_date;
                        %let yymmdd = %sysfunc(putn(&date,yymmdd6.));
                        code22_&yymmdd.
                     %end;
        ;
        length %do date=&from_date %to &to_date;
                  %let yymmdd = %sysfunc(putn(&date,yymmdd6.));
                  status22_&yymmdd.
               %end;
        $2 ;
        array status22 %do date=&from_date %to &to_date;
                         %let yymmdd = %sysfunc(putn(&date,yymmdd6.));
                         status22_&yymmdd.
                       %end;
        ;
    
        do over code22;
          status22 = put(code22, $code_to_status.);
        end;
      run;
    
    %mend;
    
    %example(20230115,20230214);