Here's a cartogram that presents Presidential election results together with morning-after newspaper front page thumbnails for each of the 50 states + DC (full-size front pages can be viewed at the Newseum).
DETAIL (right-click image above, select open-image-in-new-tab & click magnifying glass to see detail)
CODE
*==> Tile Map of 2016 Presidential election outcome w/morning headlines;
*==> US tile map coordinates from Matt Chambers
drive.google.com/file/d/0B24QRdfcy_JJZFRKLUZzMHZYbG8/view;
data StateGrid;
input statecode : $2. row column@@;
row=-row; * Flip map's y-coordinates (FL at bottom, ME at top!);
row=.875*row; * Tighten up line spacing;
StateIDcolumn=column-.365; * X-position of state abbreviation labels;
VoteIDcolumn=column+.32; * X-position of state's # of electoral votes;
cards;
AK 0 0.5 ME 0 11.5
VT 1 10 NH 1 11
WA 2 1.5 MT 2 2.5 ND 2 3.5 MN 2 4.5 WI 2 5.5 MI 2 7.5 NY 2 9.5 MA 2 10.5 RI 2 11.5
ID 3 2 WY 3 3 SD 3 4 IA 3 5 IL 3 6 IN 3 7 OH 3 8 PA 3 9 NJ 3 10 CT 3 11
OR 4 1.5 NV 4 2.5 CO 4 3.5 NE 4 4.5 MO 4 5.5 KY 4 6.5 WV 4 7.5 MD 4 8.5 DE 4 9.5
CA 5 2 AZ 5 3 UT 5 4 KS 5 5 AR 5 6 TN 5 7 VA 5 8 NC 5 9 DC 5 12
NM 6 3.5 OK 6 4.5 LA 6 5.5 MS 6 6.5 AL 6 7.5 SC 6 8.5
TX 7 4 GA 7 8
HI 8 0.5 FL 8 8.5
;
*==> Get state winners (en.wikipedia.org/wiki/United_States_presidential_election,_2016);
data stateWinner;
input statecode : $2. party $1.@@;
cards;
AL R FL R LA R NE R OK R VT D
AK R GA R ME D NV D OR D VA D
AZ R HI D MD D NH D PA R WA D
AR R ID R MA D NJ D RI D WV R
CA D IL D MI R NM D SC R WI R
CO D IN R MN D NY D SD R WY R
CT D IA R MS R NC R TN R
DE D KS R MO R ND R TX R
DC D KY R MT R OH R UT R
;
*==> Get electoral votes in each state (en.wikipedia.org/wiki/Electoral_College_(United_States));
data stateVotes;
input statecode : $2. votes@@;
cards;
AL 9 AK 3 AZ 11 AR 6 CA 55 CO 9 CT 7 DC 3 DE 3 FL 29 GA 16 HI 4 ID 4 IL 20 IN 11 IA 6 KS 6
KY 8 LA 8 ME 4 MD 10 MA 11 MI 16 MN 10 MS 6 MO 10 MT 3 NE 5 NV 6 NH 4 NJ 14 NM 5 NY 29 NC 15
ND 3 OH 18 OK 7 OR 7 PA 20 RI 4 SC 9 SD 3 TN 11 TX 38 UT 6 VT 3 VA 13 WA 12 WV 5 WI 10 WY 3
;
*==> Merge map coordinates, state winners and electoral votes;
proc sql;
create table stategridParty as
select sg.*, sw.Party, sv.Votes
from stategrid sg, statewinner sw, statevotes sv
where sg.statecode=sw.statecode and sg.statecode=sv.statecode order by sw.statecode;
proc sql noprint; * Get a list of state codes (used to map states to image files);
select statecode into :stcodes separated by ' ' from stateWinner order by 1;
*==> Thumbnails of 11-9-2016 headlines (one per state), full-size front pages available at:
*==> www.newseum.org/todaysfrontpages/?tfp_display=archive-date&tfp_archive_id=110916;
options macrogen; * A little less confusing if you see what is generated;
%macro gensymbols;
%do s=1 %to 51; * Define symbols, link to .png thumbnail w/state headlines;
%let st=%scan(&stcodes,&s);
symbolimage name=sym&st image="/folders/myfolders/News/&st..png";
%end;
* Attrobute map ties symbols to state codes values from earler SQL;
discreteattrmap name="symbols" / ignorecase=true trimleading=true;
%do s=1 %to 51;
%let st=%scan(&stcodes,&s);
value "&st" / markerattrs=(symbol=sym&st size=74pt);
%end;
enddiscreteattrmap;
%mend;
*==> Data prep done, time for fun - chart states, winners, votes, headlines!;
ods listing image_dpi=216 gpath='/folders/myfolders'; * $249 laptop is memory-challenged, so 216 dpi;
ods graphics on / reset imagefmt=jpeg noborder antialias width=22.5in height=16.5in imagename="ELECTION2016";
proc template;
define statgraph ellipseparm;
begingraph; * Map political parties to their colors;
discreteAttrMap name='PartyColor';
value 'D' / fillattrs=(color=blue);
value 'R' / fillattrs=(color=red);
endDiscreteAttrMap;
discreteAttrVar attrVar=PartyC var=Party attrMap="PartyColor";
%gensymbols; * Map state codes to .png files w/front page thumbnails;
discreteattrvar attrvar=StateMarkers var=statecode attrmap="symbols";
layout overlayequated / xaxisopts=(offsetmin=.01 offsetmax=.01 display=none)
yaxisopts=(offsetmin=.01 offsetmax=.01 display=none);
entry "HEADLINE NEWS FOR NOV 9, 2016" / valign=bottom textattrs=(size=24pt weight=bold);
ellipseparm semimajor=.49 semiminor=.49 slope=0 /* Red/blue circles represent party */
xorigin=column yorigin=row / group=partyC display=(fill);
textplot x=StateIDcolumn y=row text=statecode / /* Plot state code inside circle on left */
position=center textattrs=(color=CXffffff size=11pt weight=bold);
textplot x=voteIDcolumn y=row text=votes / /* Plot # electoral votes inside circle on right */
position=center textattrs=(color=CXffffff size=11pt weight=bold);
scatterplot x=column y=row / group=StateMarkers; /* Add morning headline thumbnails */
endlayout;
endGraph;
end;
run;
proc sgrender data=stategridParty template=ellipseparm;
run;
Awesome, Ted. I am sure your posts under the "Fun w/SAS ODS Graphics" topic are opening many eyes to the features and flexibility of this graph framework. Thanks.
At first I read the intro as "cardiogram" (instead of cartogram) and thought that might be revealing as well...
Nice job again, Ted!
BTW, readers can see the full size image by right-clicking on it and select "Open image in a new tab" in your favorite browser. Or via this link.
Cool graphs, Nice for ideas. Thanks
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
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.