BookmarkSubscribeRSS Feed
tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

USA.png

 

In a tile grid map of the U.S., NPR explains, states are reduced to a uniform size and shape to avoid the visual imbalances inherent to traditional choropleths, and the tiles are arranged to roughly approximate their real-world geographic locations.

 

So, inspired by hexagon tile map examples created in other languages by Nathan Weatherly and Matt Chambers, and with the help of some code snippets purloined from Rick Wicklin and Sanjay Matange, here's my stab at a SAS version of the United Polygons of America (code/data below).

 

*==> 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=.85*row;    * Tighten up line spacing;
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 
;
*==> Calc x, y points of hexagons for each state
     (stackoverflow.com/questions/3436453/calculate-coordinates-of-a-regular-polygons-vertices);

data StatePolygons;
set StateGrid;
radius=.54;
id+1;
angle = 2 * constant("PI") / 6;
do i = 0 to 6;
  x = column + radius * sin(i * angle);
  y = row + radius * cos(i * angle);
  output;
end;

*==> Per pupil public elementary/HS spending (https://www.census.gov/govs/school/);

data EdSpending;
input statecode : $2. percapitaspend@@;
cards;
AK 10105 AL 5031 AR 5319 AZ 4016 CA 5507 CO 5036 CT 10285 DC 10771 DE 8637 FL 5162 
GA 5616 HI 6949 IA 6356 ID 4092 IL 7291 IN 5517 KS 6072 KY 5348 LA 5905 MA 8916 
MD 8499 ME 6970 MI 6433 MN 7261 MO 5728 MS 4615 MT 6352 NC 5232 ND 7117 NE 7646 
NH 8660 NJ 10102 NM 5225 NV 4768 NY 13756 OH 6220 OK 4170 OR 5517 PA 8557 RI 8415 
SC 5349 SD 5019 TN 4943 TX 4947 UT 4199 VA 6673 VT 9849 WA 5625 WI 6527 WV 6476 WY 9252
;
*==> Merge map coordinates and state spending;

proc sql;
create table statespend as 
select sp.*, percapitaspend format=dollar7.0 
from StatePolygons sp, edspending es where sp.statecode=es.statecode;

*==> Draw the map;

proc template;
define statgraph ustemplate;
  begingraph;
  entrytitle "Per Pupil Public Elementary/HS Spending By State (2013)";
    layout overlayequated / border=false xaxisopts=(display=none) yaxisopts=(display=none);
      polygonplot id=id x=x y=y /
                  colorresponse=percapitaspend colormodel=(red blue green)
                  dataskin=matte name="spend" display=(FILL);
      continuouslegend "spend";
      textplot x=column y=row text=statecode / 
               textattrs=(color=white size=10pt weight=bold);
    endlayout;
  endgraph;
end;
run;

proc sgrender data=statespend template=ustemplate;
run;

 

14 REPLIES 14
Reeza
Super User

This is awesome!!!

tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

Check out Sanjay Matange's Micro Maps post for an explanation of LAYOUT OVERLAYEQUATED (and a neat PolygonPlot visualization!).

MichelleHomes
Meteorite | Level 14

Fabulous data visualization! Love your work @tc... I noticed you have a SAS Global Forum 2016 presenter badge. What's your presentation?

 

Kind Regards,

Michelle

//Contact me to learn how Metacoda software can help keep your SAS platform secure - https://www.metacoda.com
tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

Thanks for the shameless plug opportunity.  🙂

 

10180 - Creating and Sharing SAS® ODS Graphics with a Code Playground Based on Microsoft Office

Thursday, Apr 21, 11:30 AM - 11:50 AM – Veronese 2403/2404

 

YouTube "Trailer"

MichelleHomes
Meteorite | Level 14

Absolutely!!!! Not shameless at all... you deserve to get a huge crowd!

 

I've added it to my agenda and hope to see it and meet you in person.

 

Thanks!

Michelle

//Contact me to learn how Metacoda software can help keep your SAS platform secure - https://www.metacoda.com
Jay54
Meteorite | Level 14

The YouTube trailer / teaser is awesome.  Great idea.

Jay54
Meteorite | Level 14

Very cool indeed!  It is good to see the POLYGON plot getting some attention.  I do believe it is one of the most flexible statements in the list that allows you to do things beyond the obvious plots.  Man Happy

ChrisHemedinger
Community Manager

Brilliant! @tc, I love how you sourced and cited work from others (public sharing from Google drive, Stack Overflow).  That's how community forums work best together!

Register for SAS Innovate 2025!! The premier event for SAS users, May 6-9 in Orlando FL. Sign up now for the best deals!
ChrisHemedinger
Community Manager

BY the way @tc, anyone who wants to try your code will just need to add two more lines:

 

proc sgrender template=ustemplate;
run;

To actually render the template that you defined.  Works perfectly with that!

Register for SAS Innovate 2025!! The premier event for SAS users, May 6-9 in Orlando FL. Sign up now for the best deals!
tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

Good catch-thanks! Made correction to post. Those bad cut-and-pastes can kill you!  🙂

ChrisHemedinger
Community Manager

This example was featured in the April 2016 edition of SAS Tech Report: Tips Extra.  An alert reader points out that TEXTPLOT is a SAS 9.4 Maint 2 addition.  If you're testing with a release earlier than that, you'll find the TEXTPLOT statement generates an error and, if you remove it, of course you won't see the state name abbreviations.

Register for SAS Innovate 2025!! The premier event for SAS users, May 6-9 in Orlando FL. Sign up now for the best deals!
tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

There's more than one way to "skin" a polygon with ODS Graphics. 🙂

 

Using the label and labelattrs options to display the state labels eliminates the need for a TEXTPLOT statement: 

proc template;
define statgraph ustemplate;
  begingraph;
  entrytitle "Per Pupil Public Elementary/HS Spending By State (2013)";
    layout overlayequated / border=false xaxisopts=(display=none) yaxisopts=(display=none);
      polygonplot id=id x=x y=y /
                  colorresponse=percapitaspend colormodel=(red blue green)
                  dataskin=matte name="spend" display=(FILL) 
                  labelattrs=(color=white size=10pt weight=bold) label=statecode;            
      continuouslegend "spend";
    endlayout;
  endgraph;
end;
run;

proc sgrender data=statespend template=ustemplate;
run;

SAS Innovate 2025: Register Now

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!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 14 replies
  • 7618 views
  • 19 likes
  • 7 in conversation