Read in the ordered pairs of points for the Jack-O-Lantern graphing puzzle from Math-Aids.com into SAS, and you can use ODS Graphics to draw, color, and "light" the pumpkin in no time at all - Happy Halloween!
CODE
/* File contains points for pumpkin plot from http://math-aids.com */
filename Pumpkin "/folders/myfolders/Pumpkin.txt";
data Pumpkin(keep=shapeID x y xStem yStem xLight yLight); /* Read in pairs of points */
length shapeID $ 20. x 8 y 8;
retain shapeID;
infile Pumpkin lrecl=255;
input;
if _infile_=:'Shape' then /* Each shape preceded by "Shape n" line */
shapeID=_infile_;
else
do;
i=1;
do while(scan(_infile_, i, '(), ')^='');
x=scan(_infile_, i, '(), '); /* Points are surrounded by parentheses */
y=scan(_infile_, i+1, '(), '); /* and separated by commas */
if shapeid ='Shape 1' then do; xStem=x; yStem=y; end; /* Pumpkin stem coordinates */
if shapeid in ('Shape 10' 'Shape 11' 'Shape 12' 'Shape 7') /* Nose, mouth, eye coordinates */
then do; xLight=x; yLight=y; end;
i+2; /* Points come in pairs */
output;
end;
end;
data line(keep=function drawspace x1 y1 x2 y2 linecolor shapeid); /* Line segments to draw pumpkin */
set Pumpkin;
by shapeID notsorted;
function='line';
linecolor='black';
drawspace='datavalue';
x1=lag(x);
y1=lag(y);
x2=x;
y2=y;
if ^first.shapeID;
%macro genrender(colorStem=N, colorPumpkin=N, colorLight=N, color=black);
proc template; /* Template for pumpkin images */
define statgraph ptemplate;
begingraph;
dynamic linenum;
layout overlayequated / xaxisopts=(griddisplay=on viewmin=-12 viewmax=12 offsetmax=0)
yaxisopts=(griddisplay=on viewmin=-10 viewmax=13.5 offsetmin=.05);
scatterplot x=x y=y / markerattrs=(size=0); /* Change size if you want to view points */
entry halign=right linenum / valign=top textattrs=(size=36 weight=bold color=lightgray);
annotate;
%if &colorPumpkin=Y %then /* Color pumpkin orange */
polygonplot x=x y=y id=ShapeID / display=(fill) label=none fillattrs=(color=orange);;
%if &colorStem=Y %then /* Color stem green */
polygonplot x=xStem y=yStem id=ShapeID / display=(fill) label=none fillattrs=(color=green);;
%if &colorLight=Y %then /* "Blinking" (alternate black/yellow) for nose/eyes/mouth */
polygonplot x=xLight y=yLight id=ShapeID / display=(fill) label=none fillattrs=(color=&color);;
endlayout;
endgraph;
end;
run;
%mend;
* Create animated GIF with one incremental plot for each line (full pumpkin at begginning/end;
ods _all_ close;
options papersize=('4 in', '4 in') printerpath=gif animation=start
nodate nonumber animloop=YES animduration=1.5 NOANIMOVERLAY;
ods printer file='/folders/myfolders/Pumpkin.gif';
ods graphics / width=4in height=4in imagefmt=GIF;
%macro drawlines;
proc sql noprint; * Get frame count (1 per line segment;
select count(*) into :numlines from line;
quit;
* Display final filled/lit image before drawing lines;
%genrender(colorStem=Y, colorPumpkin=Y, colorLight=Y, color=yellow);
proc sgrender data=Pumpkin template=ptemplate sganno=line;
dynamic linenum=" ";
run;
%genrender;
options animduration=0.06;
%do l=1 %to &numlines; * Draw incremental image with lines thus far;
proc sgrender data=Pumpkin template=ptemplate sganno=line(obs=&l); dynamic linenum="&l";
run;
%end;
options animduration=1;
%genrender; * Pumpkin without any fill color;
proc sgrender data=Pumpkin template=ptemplate sganno=line; dynamic linenum=" ";
run;
%genrender(colorStem=Y); * Pumpkin with stem filled;
proc sgrender data=Pumpkin template=ptemplate sganno=line; dynamic linenum=" ";
run;
%genrender(colorStem=Y, colorPumpkin=Y); * Pumpkin stem and surface filled;
proc sgrender data=Pumpkin template=ptemplate sganno=line; dynamic linenum=" ";
run;
%do l=1 %to 10; * Fully-filled pumpkin with "blinking light";
%genrender(colorStem=Y, colorPumpkin=Y, colorLight=Y, color=black); * Light on;
proc sgrender data=Pumpkin template=ptemplate sganno=line; dynamic linenum=" ";
run;
options animduration=.25;
%genrender(colorStem=Y, colorPumpkin=Y, colorLight=Y, color=yellow); * Light off;
proc sgrender data=Pumpkin template=ptemplate sganno=line; dynamic linenum=" ";
run;
%end;
%mend;
%drawlines;
options printerpath=gif animation=stop;
run;
ods printer close;
DATA (JACK-O-LANTERN X-Y POINT PAIRS FROM MATH-AIDS.COM)
Shape 1 (-1,9) , (-0.5,10) , (0,11) , (1,12) , (2,13) , (3,13.5) , (3.5,12.5) , (2,11) , (1,10) , (1.5,8.5) (2,8) , (2,7.5) , (1,7) , (0.5,7) , (0,7) , (-1,7.5) , (-1.5,8) , (-1,9) Shape 2 (1.5,8.5) , (3,8.5) , (6,8.5) , (8,7.5) , (9.5,6.5) , (10.5,5) , (11,4) , (11.5,2) , (12,0) , (11.5,-3) (10.5,-5) , (9,-7) , (7,-8.5) , (5,-9.5) , (3,-10) , (1,-10) , (-1.5,-10) , (-3.5,-10) , (-6,-9) , (-8.5,-7) (-10,-5) , (-11.5,-2) , (-12,0) , (-11.5,2) , (-11,4) , (-10,6) , (-8,7.5) , (-6,8.5) , (-4,9) , (-2,9) , (-1,9) Shape 3 (2,8) , (5,7.5) , (7,6.5) , (8.5,5) , (9.5,3) , (10,1) , (10.5,-1) , (10,-3) , (9,-5.5) , (7,-8.5) Shape 4 (2,8) , (4,7) , (6,5) , (7,3) , (7.5,0) , (7.5,-2) Shape 5 (7.5,-3.5) , (7,-5) , (6,-7) , (5,-9.5) Shape 6 (0,-5.5) , (0.5,-8) , (1,-10) Shape 7 (2,7.5) , (3,6.5) , (4,4) , (6,1) , (4.5,1) , (1.5,1) , (4,4) Shape 8 (4.5,1) , (4.5,-1) , (4.5,-3) Shape 9 (4,-6.5) , (4,-8) , (3,-10) Shape 10 (0.5,7) , (0,5) , (0,0) , (-1,-1.5) , (0,-1.5) , (1.5,-1.5) , (0.5,0.5) , (0,0) Shape 11 (0,-1.5) , (0,-3.5) , (1.5,-3.5) , (1.5,-4.5) , (3.5,-4.5) , (3,-3) , (4.5,-3) , (7.5,-2) , (8.5,-2) , (7.5,-3.5) (6,-5) , (5,-6) , (4,-6.5) , (1.5,-7) , (1,-5.5) , (0,-5.5) , (-1,-5.5) , (-1,-7.5) , (-3,-6.5) , (-5,-5.5) (-7.5,-1.5) , (-3.5,-3) , (-4,-4.5) , (-2,-4.5) , (-1.5,-3) , (0,-3.5) Shape 12 (-1,7.5) , (-2.5,6) , (-3,5) , (-3.5,4) , (-1.5,1) , (-4,0.5) , (-6,0.5) , (-3.5,4) Shape 13 (-4,0.5) , (-4,-1) , (-3.5,-3) Shape 14 (-3,-6.5) , (-2.5,-8) , (-1.5,-10) Shape 15 (-1.5,8) , (-2.5,8) , (-4,7) , (-5.5,6) , (-7,4) , (-8,2) , (-8,0) , (-8,-2) , (-7.5,-4) , (-7,-5.5) (-5.5,-7.5) , (-3.5,-10) Shape 16 (-2,9) , (-4,8.5) , (-6,7.5) , (-8,6) , (-9.5,3.5) , (-10,2) , (-10.5,0) , (-10.5,-2) , (-9.5,-4.5) , (-8.5,-7)
Awesome, TC! You should get the "GTL Medal of Honor" or something!
Just in Time
Love it!!!
I probably should have mentioned that those seeking examples of serious applications of these tricks should check out a recent MWSUG Best Paper on Using Animation to Make Statistical Graphics Come to Life, as well as some older SAS Blogs posts on the subject - Animation using SGPLOT (includes a SAS take on the famous Gapminder dataviz), A 3D Scatter Plot Animation Macro, and Create an animation with the BY statement in PROC SGPLOT. Can't recall which of these I stole "borrrowed" code/techniques from - probably all 4.
Spooktacular!!! 🎃👍 Love your work! Definitely #dataviz delight!
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.