Oops. Revised post below.
Well, today's the day for the big parade here in Chicago for the World Series Champion Chicago Cubs, so here are a couple of short SAS programs to commemorate this once-every-108-years celebration. The first uses GTL statements - ellipseparm, polygonplot, and textplot - to chart the Cubs logo. And the second is an SGPLOT waterfall chart take on box score data from Chicago's game 7 victory over Cleveland, which shows the ups-and-downs of the Cubs lead over the Indians for every half-inning.
CODE - CUBS LOGO
* SAS ODS Graphics take on Chicago Cubs logo (Cubs color codes from teamcolorcodes.com);
data cubslogopoints;
input X Y@@; * Polygon points to mask part of red circle (make it "C" in "CUBS");
X=X-273; Y=Y-273; * Adjust x/y (model logo was 546x546 w/origin at 0,0);
ubs="UBS"; ubsX=187-273; ubsY=0; * Text string, x/y points for "UBS" part of "CUBS";
tm="TM"; tmX=400-270; tmY=273-325; * Text string, x/y points for "TM";
cards;
363 219 414 168 453 195 453 351 414 378 363 330
;
ods listing image_dpi=300 gpath='/folders/myfolders';
ods graphics on / reset antialias width=5in height=5in imagename="CUBBIESLOGO";
proc template;
define statgraph ellipseparm;
begingraph;
entrytitle "GO, CUBS, GO!";
layout overlayequated / equatetype=square
xaxisopts=(label=(none) offsetmin=0.05 offsetmax=0.05)
yaxisopts=(label=(none) offsetmin=0.05 offsetmax=0.05);
ellipseparm semimajor=273 semiminor=273 slope=0 /* Blue circle */
xorigin=0 yorigin=0 / fillattrs=(color=CX0E3386) display=(fill);
ellipseparm semimajor=202 semiminor=202 slope=0 /* White circle */
xorigin=0 yorigin=0 / fillattrs=(color=CXffffff) display=(fill);
ellipseparm semimajor=176 semiminor=176 slope=0 /* Red circle */
xorigin=0 yorigin=0 / fillattrs=(color=CXD12325) display=(fill);
ellipseparm semimajor=106 semiminor=106 slope=0 /* White Center */
xorigin=0 yorigin=0 / fillattrs=(color=CXffffff) display=(fill);
polygonplot x=X y=Y id=ubs / /* Polygon makes red circle a "C" */
display=(fill) fillattrs=(color=CXffffff);
textplot x=ubsX y=ubsY text=ubs / /* Plot red text "UBS" inside red circle */
position=right textattrs=(color=CXD12325 size=54pt weight=bold);
textplot x=tmX y=tmY text=tm / /* Plot blue text "TM" under "CUBS" */
position=bottomright textattrs=(color=CX0E3386 size=12pt weight=bold);
endlayout;
endGraph;
end;
run;
proc sgrender data=cubslogopoints template=ellipseparm;
run;
CODE - WATERFALL CHART
* SAS ODS Graphics waterfall take on Cubs lead over Indians in Game 7 of World Series;
data boxscore(keep=Team Inning Scored); /* Read box score data */
array Runs{10} Runs1-Runs10;
input Team $char18. Runs1-Runs10;
do Inning=1 to 10;
Scored=Runs(Inning);
output;
end;
cards;
Chicago Cubs 1 0 0 2 2 1 0 0 0 2
Cleveland Indians 0 0 1 0 2 0 0 3 0 1
;
proc sort data=boxscore;
by inning team;
data boxscorewaterfall; /* Transform into half-innning obs for waterfall plot */
set boxscore;
by inning;
if team=:"Chicago" then do;
inningx=put(inning,3.); /* Identify inning for xaxistable */
chicago+scored; /* Keep running score for teams */
BATTING='CHC'; /* Note who was at bat in half inning for xaxistable */
Lead=+scored; /* Add Chicago's runs to leads, subtract Cleveland's */
halfinning=inning; /* Identify half-inning for waterfall category variable */
topinning=1; /* Indicate whether top of inning (used to assign colors */
end;
else do;
Cleveland+scored;
BATTING='CLE';
Lead=-scored;
halfinning=inning+.5;
topinning=0;
end; /* Compute end of half-inning scores for xaxistable */
SCORE=compress(put(chicago,2.)||'-'||put(cleveland,2.));
data clrresp; /* Color increases/decreases to lead as green/red */
retain id "myid";
length min $ 5 max $ 5 color $20;
input min $ max $ color $;
datalines;
1 1 lightgreen
0 0 lightred
;
/* Create the waterfall chart! */
ods listing image_dpi=300 gpath='/folders/myfolders';
ods graphics on / reset antialias width=8in height=5in imagename="GAME7BOXSCORE";
proc sgplot data=boxscorewaterfall rattrmap=clrresp noautolegend;
title "2016 WORLD SERIES GAME 7: WATERFALL CHART OF CUBS LEAD OVER INDIANS";
waterfall category=halfinning response=Lead / datalabel rattrid=myid colorresponse=topinning;
xaxis display=none;
yaxis display=(noline) grid label="CHICAGO LEAD";
xaxistable inningx batting score / nolabel;
run;
Here's an alternative rendering of the box score data:
data boxscore(keep=Team Inning Scored Score); /* Read box score data */
array Runs{10} Runs1-Runs10;
input Team $char18. Runs1-Runs10;
Score = 0;
do Inning=1 to 10;
Scored=Runs(Inning);
Score + Scored;
output;
end;
cards;
Chicago Cubs 1 0 0 2 2 1 0 0 0 2
Cleveland Indians 0 0 1 0 2 0 0 3 0 1
;
title "Game 7 of 2016 World Series";
title2 "Score at End of Each Inning";
proc sgplot data=boxscore;
styleattrs datacolors=(CX0E3386 /* Cubs blue */
CXB5404B); /* Indians red */
step x=Inning y=Score / lineattrs=(thickness=3)
curvelabel markers group=Team;
yaxis values=(0 to 8) grid;
xaxis values=(1 to 10) grid;
run;
Oh, my. Baseball and statistics, America's great pastimes 😉
Love it
I work in DC but travelled to Chicago for the game. Love your graphics.
I used proc explode. Wish SAS would offer an improved banner like the ones you can get on the web. Those banners use mutiple different keys to form a more readable condensed banner.
*** *** *** * * **** *** *** ***
* * * * * * * * * * * * * * * *
* * * * * * * * * * * *
* *** * * * * * *** * * *** * *
* * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
*** *** *** *** **** *** *** ***
The banner looks a lot better in the old text editor widow with 8pt sasfont.
I use the banner to separate macros in my code.
If you type "xplo GOaCUBSaGO" on any clean command line in any window ie
program, log, output, note .. The banner will placed in the paste buffer.
The you can just paste it anywhere. The code is below.
%macro xplo ( AFSTR1 )/cmd ;
/*-----------------------------------------*\
| xplo GOaCUBSaGO |
| lower case letters produce spaces |
\*-----------------------------------------*/
note;notesubmit '%xploa';
%mend xplo;
%macro xploa
/ des = "Exploded Banner for Printouts";
options noovp;
title;
footnote;
%let uj=1;
%do %while(%scan(&afstr1.,&uj) ne );
%let uj=%eval(&uj+1);
%put uj= &uj;
%end;
data _null_;
rc=filename('__xplo', "%sysfunc(pathname(work))/__xplo");
if rc = 0 and fexist('__xplo') then rc=fdelete('__xplo');
rc=filename('__xplo');
rc=filename('__clp', "%sysfunc(pathname(work))/__clp");
if rc = 0 and fexist('__clp') then rc=fdelete('__clp');
rc=filename('__clp');
run;
filename ft15f001 "%sysfunc(pathname(work))/__xplo";
* format for proc explode;
data _null_;
file ft15f001;
%do ui=1 %to %eval(&uj-1);
put "D";
put " %scan(&afstr1.,&ui)";
%end;
run;
filename __clp "%sysfunc(pathname(work))/__clp";
proc printto print=__clp;
run;quit;
proc explode;
run;
filename ft15f001 clear;
run;quit;
proc printto;
run;quit;
filename __dm clipbrd ;
data _null_;
infile __clp;
file __dm;
input;
putlog _infile_;
put _infile_;
run;
filename __dm clear;
%mend xploa;
How to create the banner
If you type xplo GoaCUBSaGO on any command line in the old
text editor, the text will be written to the paste buffer.
You can then paste it antwhere you want.
%macro xplo ( AFSTR1 )/cmd ;
/*-----------------------------------------*\
| xplo GO CUBS GO) |
| lower case letters produce spaces |
\*-----------------------------------------*/
note;notesubmit '%xploa';
%mend xplo;
%macro xploa
/ des = "Exploded Banner for Printouts";
options noovp;
title;
footnote;
%let uj=1;
%do %while(%scan(&afstr1.,&uj) ne );
%let uj=%eval(&uj+1);
%put uj= &uj;
%end;
data _null_;
rc=filename('__xplo', "%sysfunc(pathname(work))/__xplo");
if rc = 0 and fexist('__xplo') then rc=fdelete('__xplo');
rc=filename('__xplo');
rc=filename('__clp', "%sysfunc(pathname(work))/__clp");
if rc = 0 and fexist('__clp') then rc=fdelete('__clp');
rc=filename('__clp');
run;
filename ft15f001 "%sysfunc(pathname(work))/__xplo";
* format for proc explode;
data _null_;
file ft15f001;
%do ui=1 %to %eval(&uj-1);
put "D";
put " %scan(&afstr1.,&ui)";
%end;
run;
filename __clp "%sysfunc(pathname(work))/__clp";
proc printto print=__clp;
run;quit;
proc explode;
run;
filename ft15f001 clear;
run;quit;
proc printto;
run;quit;
filename __dm clipbrd ;
data _null_;
infile __clp;
file __dm;
input;
putlog _infile_;
put _infile_;
run;
filename __dm clear;
%mend xploa;
You can use PROC EXPLODE without messing with macro. See the SAS 9.1 documentation.
An example is
ods listing;
filename ft15f001 temp;
proc explode;
parmcards;
GO CUBS GO
;
Nice to still see a use for PROC EXPLODE now that lineflow is in the museum !
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.