BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
sas_user_1001
Obsidian | Level 7

I have a SAS dataset called "holidays" that is structured as shown below that spans 1985-2023. I have dummy variables for the Friday and the weekend, and most importantly holidays.

sas_user_1001_0-1723222521440.png

I am trying to write a loop which works through a list of all months and days of the week to determine what percentage of a day of the week, for a given month, falls on a holiday. For instance, what percentage of Monday's in January have been a federal holiday between 1985 and 2023? What percentage of Tuesday's in January, etc... Below is my code thus far:

 

%let m_list = 1 2 3 4 5 6 7 8 9 10 11 12;
%let d_list = 1 2 3 4 5 6 7;
 
%macro holidays(list1,list2);
 
%local month day next_month next_day;
 
%do month = 1 %to %sysfunc(countw(&m_list));
    %let next_month = %scan(&m_list,&month);
      %do day = 1 %to %sysfunc(countw(&d_list));
        %let next_day = %scan(&d_list,&day);
 
proc freq data = holidays;
where Month = &next_month and dow = &next_day;
table HolDum / out = prob_&next_month._&next_day;
 
data _null_;
set prob_&next_month._&next_day;
if HolDum = 0 then call symput("M&next_month._&next_day._0",PERCENT/100);
else if HolDum = 1 then do;
call symput("M&next_month._&next_day._1",PERCENT/100);
end; run;
 
%end;
%end; 
%mend holidays;
%holidays(&m_list,&d_list)
 
%put &M1_1_0 &M1_1_1 &M1_2_0 &M1_2_1;
 
Where I am stuck is the data _null_ step--the loop does not seem to be assigning percentages for the holiday dummy variable to the variable name (as verified when I run the %put statement). Can someone help me troubleshoot this. I'm relatively new to SAS so this might be a SAS issue I'm not seeing, or perhaps just a logic issue I'm missing. Thanks.
1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

@sas_user_1001 wrote:
If I'm understanding correctly, you are asking why I have %put at the end for the binary variables? I am simply wanting to see that the code assigned the percentages as I intended; it's just a check. Those percentages get called up and used later on in the code.

Placing that much calculation result into macro variables is usually a poor idea.

How exactly are those macro values used later?

 

And the point is that the macro variables involved with your %put do no exist after the macro ends as they are local in scope with code as written.

View solution in original post

9 REPLIES 9
Tom
Super User Tom
Super User

Why are you trying to print the value of LOCAL macro variables after the macro has finished running?

sas_user_1001
Obsidian | Level 7
If I'm understanding correctly, you are asking why I have %put at the end for the binary variables? I am simply wanting to see that the code assigned the percentages as I intended; it's just a check. Those percentages get called up and used later on in the code.
ballardw
Super User

@sas_user_1001 wrote:
If I'm understanding correctly, you are asking why I have %put at the end for the binary variables? I am simply wanting to see that the code assigned the percentages as I intended; it's just a check. Those percentages get called up and used later on in the code.

Placing that much calculation result into macro variables is usually a poor idea.

How exactly are those macro values used later?

 

And the point is that the macro variables involved with your %put do no exist after the macro ends as they are local in scope with code as written.

sas_user_1001
Obsidian | Level 7
Gotcha. I was overlooking the local component in doing this. Makes sense. Thanks for the insight.
sas_user_1001
Obsidian | Level 7

I wanted to circle back to this point. I was able to specify the variable names using symputx with 'G' to make these global variables. The code now works due to this insight.

ballardw
Super User

Before you started down this macro path did you have code that worked for some period that did not involve any macro variables or coding?

If not the basic approach is to do such. Then see if a macro is even needed.

 

Is your HOLDUM variable supposed to be the indicator that the day is a holiday?

If so you may want to consider either of these codes:

proc tabulate data=holidays;
  class month dow;
  var holdum;
  table month,
        dow*holdum*mean*f=percent8.2;
run;

proc tabulate data=holidays;
  class month dow holdum;
  table month,
        dow*holdum*pctn<month>
       /misstext=' ';
run;

Which uses the power of the procedure to do the grouping and counting.

Or

Proc freq data=holidays;
  tables month*dow*holdum/outpercent;
  ods output crosstabfreqs=myoutput;
run;

though the output data set Myoutput would need a bit of massaging to get just the holidays. Look at the variable ROWPERCENT where HOLDUM=1.

 

I have no idea what your dummy variables mean or what role they play in this exercise. So you may discuss them.

sas_user_1001
Obsidian | Level 7
Yes, if HolDum = 1 then it is a federal holiday; 0 otherwise. These %ages I'm trying to utilize are used when I do a data simulation later on. I want the frequency these holidays show up in historical data to show up at the same rate in the simulation.
ballardw
Super User

If your process is modeling dates then you should be able to get one of the HOLIDAY functions with that to tell if the date is a holidy.

Tom
Super User Tom
Super User

Assuming that HOLDUM is coded as 1/0 with 1 meaning HOLIDAY you can get your results using PROC SUMMARY.  The MEAN of a 1/0 variable is the percent of times the value was 1.

proc summary data=holidays nway;
  class month dow ;
  var holdum;
  output out=percent_holiday mean=percent_holiday;
run;

And you can also skip the macro variables since you could just use the dataset to drive your simulation.

 

Let's try it:

data holidays;
  do date='01JAN1985'd to '31DEC2023'd ;
    month=month(date);
    dow=weekday(date);
    holdum=0<holidaycount(date);
    output;
  end;
  format date yymmdd10.;
run;

proc summary data=holidays nway;
  class month dow ;
  var holdum;
  output out=percent_holiday mean=percent_holiday;
run;

If we check how often Thursday in November is a holiday we get just over 26% of the time.

11 5 3 167 0.26347

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 9 replies
  • 636 views
  • 2 likes
  • 3 in conversation