Tally marks aren't just for prison walls anymore. 😀 Here's a SAS ODS Graphics take on a Tally Mark-based New Year's Eve Countdown Timer. Happy New Year, all!
* Fun With SAS ODS Graphics: Tally Mark New Year's Eve Countdown Timer (Vector + Text Plots)
Reference: https://en.wikipedia.org/wiki/Tally_marks;
data tally; * Create x/y points for 10 tally marks for countdown;
retain y 1 yo -1 yt 1.5; * y-values for vectors, text;
do x=0 to 10; * 8 Vertical lines;
xo=x;
if ^(1<=x<=4 or 6<=x<=9) then xo=.; * Vertical lines only at 1-4, 6-9;
xt=x; count=put(x,2.); * Display # seconds (0-10) above tally marks;
output;
end;
count=.; xt=.; yt=.;
xo=0; yo=-.6; x=5; y=.6; output; * 2 diagonal lines at 5 and 10 seconds;
xo=5; yo=-.6; x=10; y=.6; output;
proc sql; * Create countdown frames, removing 1 mark with each new frame;
create table frames as
select t2.frame, t.* from tally t, (select distinct x as frame from tally) t2
union all
select 11, t.* from tally t /* Dupe 1st frame ('10') to show it twice as long */
order by frame desc;
options nobyline; * Animated GIF initialization;
ods _all_ close; * Frame duration is 1 second for countdown;
options papersize=('6 in', '6 in') printerpath=gif animation=start
nodate nonumber animloop=YES animduration=1 NOANIMOVERLAY ;
ods printer file='/home/ted.conway/NewYear2026/NewYear2026.gif';
ods graphics / width=6in height=6in imagefmt=GIF border=off;
* Create countdown animated GIF (vector + text plots);
proc sgplot data=frames(where=(frame>=x)) nowall noborder noautolegend;
by frame notsorted; * One for each second with tally marks;
styleattrs backcolor=black;
inset "2025" / textattrs=(color=white weight=bold size=48pt) position=bottom; * Current year;
text x=xt y=yt text=count / contributeoffsets=none textattrs=(color=white weight=bold size=24pt) strip; * Display 0-10 above tally marks;
vector x=x y=y / noarrowheads xorigin=xo yorigin=yo lineattrs=(color=white thickness=12pt); * Tally marks for 0-10 (arrowless vectors);
xaxis display=none values=(-1 11) offsetmax=0 offsetmin=0; * Suppress axes;
yaxis display=none values=(-2 2) offsetmax=0 offsetmin=0;
* Final frame to display Happy New Year! + 2026;
data happynewyear; retain xt2 5 yt2 0 txt 'HAPPY*NEW YEAR!'; output;
options animduration=2.5; * Increase duration of final frame to 2.5 seconds;
proc sgplot data=happynewyear nowall noborder noautolegend;
styleattrs backcolor=black;
inset "2026" / textattrs=(color=white weight=bold size=48pt) position=bottom; * New year;
text x=xt2 y=yt2 text=txt / splitchar='*' splitpolicy=splitalways contributeoffsets=none textattrs=(color=white weight=bold size=60pt) strip; * Happy New Year greeting;
xaxis display=none values=(-1 11) offsetmax=0 offsetmin=0; * Suppress axes;
yaxis display=none values=(-2 2) offsetmax=0 offsetmin=0;
run;
options printerpath=gif animation=stop; * Wrap-up animated GIF creation;
run;
ods printer close;
A Rough Draft
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.
Ready to level-up your skills? Choose your own adventure.