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 open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
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.