Here is the beer bottle version with side-by-side bars.
/* Modification of
* Fun With SAS ODS Graphics - Is the Glass Half-Trump or Half-Biden? (Yet Another Election Map)
* to show each opponents support in beer bottles
*
* Data randomly generated
*/
*==> Generate USA cartogram map x/y coordinates from inline layout of state codes;
data state_cartogram_points(keep=statecode x y);
length statecode $2;
format x y 3.;
input;
line = _infile_;
if line ne: '/*';
y + 1; * y-axis location of state name;
do _n_ = 1 to countw(line,', ');
statecode = scan(line, _n_, ', ');
x = index(line, statecode);
output;
end;
datalines;
/* -|----10---|----20---|----30---|----40---|----50---| */
AK ME
VT, NH
WA, MT, ND, MN, WI, MI, NY, MA, RI
ID, WY, SD, IA, IL, IN, OH, PA, NJ, CT
OR, NV, CO, NE, MO, KY, WV, MD, DE
CA, AZ, UT, KS, AR, TN, VA, NC, DC
NM, OK, LA, MS, AL, SC
TX GA
HI FL
;
proc sort; by statecode; run;
data state_votes;
set state_cartogram_points;
by statecode;
if first.statecode;
call streaminit (123);
name = 'Jrrgl Bmurgrgly ';
pct = round(47.5 + rand('uniform', 0, 5), 0.1);
_tot = pct;
output;
name = 'Dorggles Jrgllulrm';
do _n_ = 1 to 1000 until (_tot + pct <= 100);
pct = round(47.5 + rand('uniform', 0, 5), 0.1);
end;
_tot + pct;
output;
name = 'Erggglglia Gluggglr';
pct = 100 - _tot;
output;
keep statecode name pct;
format pct 6.2;
run;
*==> Merge voting data and map points,
Generate points for polygons (rectangles) to make "glasses" showing each candidate's share,
Generate points for ellipses for top (Trump) and bottom (Biden) of "glasses";
%macro rect(xvar=px, yvar=py, x=, y=, w=0.90, h=pct, ymult=3.5);
&xvar = &x; &yvar = (&y + 1) * &ymult; output;
&yvar = &yvar - &h * &ymult / 100; output;
&xvar = &x + &w; output;
&yvar = (&y + 1) * &ymult; output;
%mend;
%macro bottles(xvar=pxo, yvar=pyo, x=x, y=y, w=0.91, h=96, ymult=3.5);
/* x1,y1 is lower left x2,y2 is upper right */
h = 0.96 * &ymult;
h1 = 0.60 * &ymult;
h2 = 0.76 * &ymult;
x1 = &x; y1 = (&y + 1) * &ymult;
x2 = x1 + 0.91; y2 = y1 - h;
polygon_id+1;
&xvar = x1; &yvar = y1; output;
&yvar = y1-h1; output;
&xvar = x1+.15; &yvar = y1-h2; output;
&yvar = y2; output;
&xvar = x2-.15; output;
&yvar = y1-h2; output;
&xvar = x2; &yvar = y1-h1; output;
&yvar = y1; output;
x1 + 1;
x2 + 1;
x3 + 1;
x4 + 1;
polygon_id+1;
&xvar = x1; &yvar = y1; output;
&yvar = y1-h1; output;
&xvar = x1+.15; &yvar = y1-h2; output;
&yvar = y2; output;
&xvar = x2-.15; output;
&yvar = y1-h2; output;
&xvar = x2; &yvar = y1-h1; output;
&yvar = y1; output;
%mend;
options mprint;
data map_polygons (rename=name=who);
merge
state_cartogram_points
state_votes
;
by statecode;
if name in: ('Jrrgl', 'Dorggles');
if name =: 'Dorggles' then dx_who = 0; else dx_who = 1;
polygon_id+1;
%rect (x=x + dx_who, y=y);
call missing (px, py);
if first.statecode then do;
pxt = x + 1;
pyt = (y + 1) * 3.5 + .5;
output;
call missing(pxt, pyt);
%bottles ();
call missing (pxo, pyo);
end;
format px py pxt pyt pxo pyo 7.2 polygon_id dx_who 4.;
run;
options nomprint;
*==> Map and bar charts of vote shares - polygon + ellipse + text plots);
*ods listing image_dpi=300 gpath='/temp';
*ods graphics on / reset antialias width=11in height=8.5in imagename="PresidentialElection";
ods listing image_dpi=96 gpath='/temp';
ods graphics on / reset antialias width=2200px height=1700px imagename="PresidentialElection";
proc template;
define statgraph ustemplate;
begingraph / subpixel=on; * Define Dem/Rep color attributes;
discreteattrmap name="who_colors";
value "Jrrgl Bmurgrgly" / fillattrs=(color=red);
value "Dorggles Jrgllulrm" / fillattrs=(color=blue);
enddiscreteattrmap;
discreteattrvar
attrvar=who_color
var=who
attrmap="who_colors"
;
layout overlayequated /
xaxisopts=(display=none thresholdmin=0 thresholdmax=0)
yaxisopts=(display=none reverse=true)
;
layout gridded / columns=1 valign=top; * Titles (Insets);
entry textattrs=(size=24pt weight=bold color=black) "ELECTION 2020";
entry textattrs=(size=8pt) " ";
entry textattrs=(size=16pt weight=bold color=black) "WHO HAS MORE? "
textattrs=(size=16pt weight=bold color=red) "JRRGL"
textattrs=(size=16pt weight=bold color=black) " OR "
textattrs=(size=16pt weight=bold color=blue) "DORGGLES"
textattrs=(size=16pt weight=bold color=black) "?";
endlayout;
polygonplot x=px y=py id=polygon_id /
display=(fill)
group=who_color
includemissinggroup=false; * Rectangles showing candidates' vote shares;
polygonplot x=pxo y=pyo id=polygon_id /
display=(outline)
includemissinggroup=false;
textplot x=pxt y=pyt text=statecode / textattrs=(color=gray66 weight=bold size=8pt);
entry
" NOTES: "
"1. PERCENTAGES BASED ONLY ON VOTES CAST FOR Dorggles AND Jrrgl."
"2. VOTING DATA FROM RAND('UNIFORM') "
/ valign=bottom;
;
endlayout;
endgraph;
end;
run;
proc sgrender data=map_polygons template=ustemplate; * Generate the chart!;
run;
... View more