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
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and save with the early bird rate—just $795!
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.