%let name=us_weekly_mortgage_animation; /* Set your current-working-directory (to read/write files), if you need to ... %let rc=%sysfunc(dlgcdir('c:\someplace\public_html')); */ filename odsout '.'; /* Similar to graph in this post by Leonard Kiefer: https://twitter.com/lenkiefer/status/1121427487538536448 Using data from: http://www.freddiemac.com/pmms/ historicalweeklydata.xls */ proc import datafile="../ods4/historicalweeklydata.xls" dbms=xls out=historical_data; range='Full History$a8:b0'; getnames=no; run; proc import datafile="../ods4/historicalweeklydata.xls" dbms=xls out=data_2019; range='1PMMS2019$a8:b0'; getnames=no; run; data my_data; set historical_data (rename=(a=date b=rate)) data_2019 (rename=(a=date b=rate)); rate=rate/100; if date>='01jan2017'd then output; run; proc sql noprint; select max(date) format=nldate. into :maxdate separated by ' ' from my_data; quit; run; proc sort data=my_data out=anim_data; by date; run; data anim_data; set anim_data; obs_number=_n_; run; /* determine how many times each obsn needs to be repeated in the data */ proc sort data=anim_data out=anim_data; by descending date; run; data anim_data; set anim_data; repeats=_n_; run; data anim_data (keep = frame_number date rate); set anim_data; do loop = 1 to repeats; frame_number=obs_number+(loop-1); output; end; run; proc sort data=anim_data out=anim_data; by frame_number date; run; data anim_data; set anim_data; by frame_number; if last.frame_number then rate_dot=rate; run; options papersize=('8 in', '6 in') printerpath=gif animation=start animduration=.10 animloop=yes noanimoverlay; ods printer file="&name..gif"; ods graphics / /*width=8in height=6in*/ width=800px height=600px imagefmt=gif; options nodate nonumber nobyline; ods listing select none; title1 c=gray33 h=18pt "U.S. 30-Year Residential Mortgage Rate"; footnote c=gray77 h=11pt "Data source: Freddie Mac Primary Mortgage Market Survey (weekly data through &maxdate)"; proc sgplot data=anim_data noborder noautolegend; format date date9.; format rate rate_dot percent7.2; by frame_number; format rate percent7.1; series x=date y=rate; scatter x=date y=rate_dot / datalabel datalabelpos=right datalabelattrs=(size=9pt); yaxis display=(nolabel noline noticks) values=(.0375 to .0500 by .0025) valueattrs=(size=10pt) grid gridattrs=(pattern=dot color=gray66) offsetmin=0 offsetmax=0; xaxis display=(nolabel noline) values=('01jan2017'd to '01jan2020'd by year) valueattrs=(size=10pt) offsetmin=0 offsetmax=0; refline '01jan2017'd '01apr2017'd '01jul2017'd '01oct2017'd '01jan2018'd '01apr2018'd '01jul2018'd '01oct2018'd '01jan2019'd '01apr2019'd '01jul2019'd '01oct2019'd '01jan2020'd / axis=x lineattrs=(pattern=dot color=gray66); run; proc sql noprint; select max(frame_number) into :maxfrm separated by ' ' from anim_data; quit; run; /* generate a few more of the last graph, so the animation will appear to 'pause' for a while at the end */ %macro doit; proc sgplot data=anim_data (where=(frame_number=&maxfrm)) noborder noautolegend; format date date9.; format rate rate_dot percent7.2; by frame_number; format rate percent7.1; series x=date y=rate; scatter x=date y=rate_dot / datalabel datalabelpos=right; yaxis display=(nolabel noline noticks) values=(.0375 to .0500 by .0025) grid gridattrs=(pattern=dot color=gray66) offsetmin=0 offsetmax=0; xaxis display=(nolabel noline) values=('01jan2017'd to '01jan2020'd by year) offsetmin=0 offsetmax=0; refline '01jan2017'd '01apr2017'd '01jul2017'd '01oct2017'd '01jan2018'd '01apr2018'd '01jul2018'd '01oct2018'd '01jan2019'd '01apr2019'd '01jul2019'd '01oct2019'd '01jan2020'd / axis=x lineattrs=(pattern=dot color=gray66); %mend; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; %doit; options printerpath=gif animation=stop; ods printer close; quit; ODS HTML CLOSE; ODS LISTING;