Home > OS >  SAS - Using a loop to call a macro with different parameters
SAS - Using a loop to call a macro with different parameters

Time:10-13

I'm new to SAS and I'm trying to automate the process of calling a macro with different parameters.

Here's the macro I want to call.

%macro expo(month, year);                                          
    data policy_&month&year;
        set lastpol2;
        by policy_no;
        drop uwmonth;
        accidentmonth = &month&year;      
run;
%mend;

I need to call this macro for every month and every year since 2016, so the current method is to simply call the macro multiple times.


%expo(1,2016);
%expo(2,2016);
%expo(3,2016);
%expo(4,2016);
%expo(5,2016);

...
...

%expo(10,2021);
%expo(11,2021);
%expo(12,2021);

Instead of having this long list, I want to create a loop that gets the current year and iterates over every month for each year. My approach for this is by writing a macro to call the other macro multiple times with different parameters, here's my attempt so far.

%macro create_policies();
    %let current_year = year(input("&sysdate9",date9.));
    %let policy_start_year = 2016;
    %if policy_start_year <= current_year %then
        %do i = 1 %to 12;
            %expo(&i, &policy_start_year);
        %end;
        %let policy_start_year = &policy_start_year   1;

run;
%mend;

%create_policies()

So I'm trying to loop through 1 to 12 and call the macro each time using number in the loop. After the index 12 has been reached, I want the year to change to the next year and for the process to repeat until it's finished the current year.

Any help or pointers would be great.

Thanks.

CodePudding user response:

You're on the right track. SAS has a built-in function called intnx() that shifts dates and times to make this easier. Convert your years into SAS dates, but align the current year to December and the start year to January:

%let policy_start_year = %sysfunc(mdy(1, 1, 2016));
%let current_year      = %sysfunc(intnx(year, %sysfunc(today()), 0, E));

%put Start date: %sysfunc(putn(&policy_start_year, date9.));
%put End date: %sysfunc(putn(&current_year, date9.));

Output:

Start date: 01JAN2016
End date: 31DEC2021

The actual day of the month itself does not matter for this purpose.

Use the intck() function to count the number of months between the start date and the end date, then loop and increment the start date one month at a time until you reach the end date. For example, if you start on 01JAN2016, 1 month from the start date is 01FEB2016, 2 months from the start date is 01MAR2016, etc. You can grab the year and month value from each date you shift using the month() and year() functions.

%macro create_policies(start_year);
    %let current_year      = %sysfunc(intnx(year, %sysfunc(today()), 0, E));
    %let policy_start_year = %sysfunc(mdy(1, 1, &start_year.));

    %do i = 0 %to %sysfunc(intck(month, &policy_start_year., &current_year.) );
        %let date  = %sysfunc(intnx(month, &policy_start_year., &i.) );

        %let month = %sysfunc(month(&date.));
        %let year  = %sysfunc(year(&date.));

        %put date: %sysfunc(putn(&date., date9.)) | year: &year. | month: &month.;

        %expo(&month., &year.);
    %end;

%mend;

%create_policies(2016);

Output:

date: 01JAN2016 | year: 2016 | month: 1
date: 01FEB2016 | year: 2016 | month: 2
date: 01MAR2016 | year: 2016 | month: 3
date: 01APR2016 | year: 2016 | month: 4
...
date: 01NOV2020 | year: 2020 | month: 11
date: 01DEC2020 | year: 2020 | month: 12
date: 01JAN2021 | year: 2021 | month: 1
date: 01FEB2021 | year: 2021 | month: 2
...
date: 01SEP2021 | year: 2021 | month: 9
date: 01OCT2021 | year: 2021 | month: 10
date: 01NOV2021 | year: 2021 | month: 11
date: 01DEC2021 | year: 2021 | month: 12
  • Related