/* Create data set with date & daily percentage change in DOW */ data citiday; set sashelp.citiday (keep=date snydjcm); format percent Percent8.2; retain prev .; if prev NE 0 or prev NE . then do; diff = snydjcm - prev; percent = diff / prev; end; weekday = weekday( date ); week = week( date ); if diff ne . then output; if snydjcm NE . then prev = snydjcm; run; /* Create dataset for the starting day of each month spanning the original date range; */ data month_starts(keep=year month date weekday week enddate endwkday endweek); format year F4.; format date Date7.; set citiday end=lastobs; retain mindate 100000; retain maxdate 0; mindate = min(date, mindate); maxdate = max(date, maxdate); format enddate Date7.; if lastobs then do; startyear = year(mindate); endyear = year(maxdate); startmonth = month(mindate); mon = startmonth; year = startyear; do i=startyear to endyear by 1; do month=mon to 12 by 1; date = mdy( month, 1, i ); if( month EQ 12 ) then do; nm = 1; ny = i+1; end; else do; nm = month+1; ny = i; end; enddate = mdy( nm, 1, ny ) - 1; weekday = weekday( date ); week = week( date ); year = year( date ); endwkday = weekday( enddate ); endweek = week( enddate ); if( date < maxdate ) then output; else date = maxdate-1; end; mon = 1; end; if( date < maxdate ) then do; date = maxdate; weekday = weekday( date ); week = week( date ); year = year( date ); output; end; end; run; /* Create the data for the series plot to draw the line boundaries */ data month_boundaries (keep=year wd wk); set month_starts; retain pts 1; if weekday > 1 then do; if month = 12 then pts = 7; else pts = 7; do i=1 to pts by 1; select (i); when (1) do; wd = 1; wk = endweek; end; when (2) do; wd = 1; wk = week; end; when (3) do; wd = weekday; wk = week; end; when (4) do; wd = weekday; wk = week - 1; end; when (5) do; wd = 8; wk = week - 1; end; when (6) do; wd = 8; if( endwkday = 7 ) then wk = endweek; else wk = endweek - 1; end; when (7) do; wd = .; wk = week - 1; /* insert . to break line */ end; end; wd = wd - 0.5; wk = wk + 0.5; output; end; end; else if weekday = 1 then do; do i=1 to 5 by 1; select (i); when (1) do; wd = 1; wk = endweek; end; when (2) do; wd = 1; wk = week-1; end; when (3) do; wd = 8; wk = week-1; end; when (4) do; wd = 8; if( endwkday = 7 ) then wk = endweek; else wk = endweek - 1; end; when (5) do; wd = .; wk = week; end; end; wd = wd - 0.5; wk = wk + 0.5; output; end; end; /* Add closing boundary for december */ if( month = 12 ) then do; if( endwkday = 7 ) then do; wd = 7.5; wk = endweek + 0.5; output; wd = 0.5; wk = endweek + 0.5; output; wd = .; wk = week; output; end; else do; wd = 7.5; wk = endweek - 1 + 0.5; output; wd = endwkday - 0.5; wk = endweek - 1 + 0.5; output; wd = endwkday - 0.5; wk = endweek + 0.5; output; wd = 0.5; wk = endweek + 0.5; output; wd = .; wk = week; output; end; end; run; proc format; value wkdayname 1 = 'Sunday' 2 = 'Monday' 3 = 'Tuesday' 4 = 'Wednesday' 5 = 'Thursday' 6 = 'Friday' 7 = 'Saturday' ; value monthname 1 = 'JAN' 2 = 'FEB' 3 = 'MAR' 4 = 'APR' 5 = 'MAY' 6 = 'JUN' 7 = 'JUL' 8 = 'AUG' 9 = 'SEP' 10 = 'OCT' 11 = 'NOV' 12 = 'DEC' ; run; /* Create the data for the block plot */ data month_blocks(keep=year month midmonthweek prevwk); set month_starts end=lastobs; by year; month = month( date )-1; wkofyear = week( date ); retain prevwk .; format month monthname.; midmonthweek = (wkofyear + prevwk)/2; if first.year then do; end; else do; output; end; prevwk = wkofyear; if last.year then do; midmonthweek = (wkofyear + week(mdy(12,31,year)))/2; month = 12; output; end; run; /* Merge data sets for sgrender */ data combined; merge citiday(where=(date < '1Jan1989'd) ) month_boundaries(where=(year=1988)) month_blocks(where=(year=1988)); format weekday wkdayname. wd wkdayname.; label week='Week' weekday="Day of Week"; day = day(date); run; proc template; define statgraph cal_heatmap; begingraph / designheight=210 designwidth=1200; entrytitle 'Calendar Heatmap of % daily change of the DOW Jones composite index in 1988'; rangeattrmap name="rmap"; range min - 0 / rangecolormodel=(darkred red yellow); range 0 - max / rangecolormodel=(yellow green darkgreen); endrangeattrmap; rangeattrvar attrmap="rmap" attrvar=cvar var=percent; layout overlay / walldisplay=none xaxisopts=(display=none) yaxisopts=(display=(tickvalues) reverse=true linearopts=(tickvaluelist=(1 2 3 4 5 6 7)) ); heatmapparm x=week y=weekday colorresponse=cvar/ name="heatmap" xgap=1 ygap=1; seriesplot x=wk y=wd / connectorder=xvalues break=true lineattrs=(color=black thickness=1) primary=true; innermargin / align=bottom; blockplot x=prevwk block=month / valuehalign=center display=(values); endinnermargin; continuouslegend "heatmap" / valuecounthint=3; endlayout; endgraph; end; run; proc sgrender data=combined template=cal_heatmap; run;