/* This is a sas/graph imitation of the following map... http://cber.utk.edu/census/2k/map1.gif The maps.us I am using in this example is the new v9.2 map, which is a little different from the v9.1.3 map - you'll have to tweak the code a little to use it with v9.1.3 ... Note that the boxes around the Alaska, Hawaii, and PR, as well as the text to the left of the legend, are somewhat hard-coded and if *anything* about the way this map is run changes, then these will likely need some tweaking to line up correctly. (Such changes include, but are not limited to: font used, ranges of data values, font size, font rendering, map used, etc.) */ /* This is the base name that will be used for the gif & html files, etc */ %let name=change; /* The files will be written to your current-directory, wherever that might be */ filename odsout '.'; /* Create my own copy of the US Map dataset */ data my_us; set maps.us; /* Add an 'order' variable, in case you have to re-sort the map later */ order=_n_; /* Add 2-character state abbreviation, which is more readable */ st=fipstate(state); run; data my_us; set my_us; /* Move Alaska & Hawaii into better positions */ if st='AK' then do; y=y+.475; x=x-.06; end; if st='HI' then do; x=x-.21; end; run; proc format; value bin_fmt 1='39.6 or more' 2='26.4 to 39.5' 3='13.2 to 26.3' 4='0 to 13.1' 5='Less than 0' ; run; data mydata; format color_bin bin_fmt.; input st $ 1-2 pct_change; state=stfips(st); if (pct_change >= 39.6) then color_bin=1; else if (pct_change >= 26.4) then color_bin=2; else if (pct_change >= 13.2) then color_bin=3; else if (pct_change >= 0) then color_bin=4; else color_bin=5; datalines; DC -5.7 AK 14.0 HI 9.3 WA 21.1 OR 20.4 CA 13.8 AZ 40.0 NV 66.3 ID 28.5 UT 29.6 MT 12.9 WY 8.9 CO 30.6 NM 20.1 ND 0.5 SD 8.5 NE 8.4 KS 8.5 OK 9.7 TX 22.8 LA 5.9 AR 13.7 MO 9.3 IA 5.4 MN 12.4 WI 9.6 IL 8.6 MI 6.9 IN 9.7 OH 4.7 KY 9.7 TN 16.7 MS 10.5 AL 10.1 FL 23.5 GA 26.4 SC 15.1 NC 21.4 VA 14.4 WV 0.8 PA 3.4 NY 5.5 VT 8.2 NH 11.4 ME 3.8 MD 10.8 DE 17.6 NJ 8.9 CT 3.6 RI 4.5 MA 5.5 PR 8.1 ; run; /* Add a variable containing info telling ods what to do when you mouse-over or click a state */ data mydata; set mydata; length myhtmlvar $200; statestring=' '; statestring=state; if state<10 then statestring='0'||trim(left(statestring)); myhtmlvar= /* Here is the chart tip you see when you mouse over a state */ 'title='|| quote( trim(left(fipnamel(state)))||': '||trim(left(put(pct_change/100,percentn7.1)))||' ') ||' '|| /* Here is the link you follow when you click on a state */ 'href="http://quickfacts.census.gov/qfd/states/'||trim(left(statestring))||'000.html"'; run; proc sql; create table state_anno as select uscenter.*, mydata.st, mydata.pct_change, mydata.color_bin, mydata.myhtmlvar as html from maps.uscenter left join mydata on uscenter.state = mydata.state; quit; run; /* Move Alaska & Hawaii labels just like you moved the states */ data state_anno; set state_anno; if st='AK' then do; y=y+.475; x=x-.06; end; if st='HI' then do; x=x-.21; /* and move it a little more, so the label is beside the state */ x=x-.015; y=y-.015; end; run; /* don't utilize the ocean label positions for a few of the states */ data state_anno; set state_anno; if st in ('VT' 'NH') and (ocean='Y') then foo=1; else output; run; /* Annotate state abbreviation and data value */ data state_anno; set state_anno; length function $ 8 style color cbox cborder $ 12 position $ 1 text $ 100; retain flag 0 function 'label' xsys '2' ysys '2' hsys '3' when 'a' position '5'; function='label'; text=trim(left(st)); size=1.8; position='5'; if ocean='Y' then do; function='label'; size=1.7; style='"arial/bo"'; color='black'; cborder='gray99'; position='6'; if (color_bin eq 1) then cbox='cx006837'; else if (color_bin eq 2) then cbox='cx31a354'; else if (color_bin eq 3) then cbox='cx78c679'; else if (color_bin eq 4) then cbox='cxc2e699'; else if (color_bin eq 5) then cbox='cxffffcc'; else cbox=''; text=trim(left(st))||' '||trim(left(pct_change)); output; function='move'; flag=1; end; else if flag=1 then do; function='draw'; size=.01; flag=0; end; if (function in ('move' 'draw')) then output; else do; function='label'; size=1.7; style='"arial/bo"'; color='black'; cbox=''; cborder=''; position='b'; text=trim(left(st)); output; position='e'; text=trim(left(pct_change)); output; end; /* if st='FL' then x=x+.037; if st='MI' then x=x+.02; if st='NY' then x=x+.02; if st='OK' then x=x+.02; if st='DE' then x=x+.015; if st='DC' then x=x-.009; if st='RI' then x=x+.005; if st='RI' then y=y-.005; if st='LA' then x=x-.02; if st='MN' then x=x-.02; if st='CA' then x=x-.02; if st='AK' then x=x-.02; if st='AK' then y=y+.02; if st='SC' then y=y+.01; if st='CT' then y=y+.005; if st='MD' then y=y+.007; if st='MA' then y=y+.005; if st='GA' then y=y+.007; if st='GA' then x=x-.007; if st='TN' then y=y+.005; if st='VT' then y=y+.007; if st='NH' then y=y+.003; if st='ID' then y=y-.02; */ run; /* Annotate boxes around HI & AK */ data box_anno; length function $ 8 style color $ 12 position $ 1; retain xsys '2' ysys '2' hsys '3' when 'a' color 'graycc'; /* Hawaii box */ function='poly'; x=-.442; y=-.208; output; function='polycont'; x=x+.09; output; y=y+.08; output; x=x-.09; output; y=y-.08; output; /* Puerto Rico box */ function='poly'; x=.275; y=-.208; output; function='polycont'; x=x+.09; output; y=y+.04; output; x=x-.09; output; y=y-.04; output; /* Alaska box */ function='poly'; x=-.442; y=.265; output; function='polycont'; x=x+.17; output; y=y+.15; output; x=x-.17; output; y=y-.15; output; run; data title_anno; length function $ 8 style color $ 12 position $ 1 text $ 100; retain function 'label' xsys '3' ysys '3' hsys '3' when 'a'; style='"arial/bo"'; color='black'; size=2.8; position='5'; x=60; y=97; text='Figure 1. Percent Change in Resident Population for the 50 States,'; output; y=93; text='the District of Columbia, and Puerto Rico: 1990 to 2000'; output; size=1.5; position='6'; x=56; y=4; text='(Not) Prepared by the Geography Division'; output; run; /* enhance the legend with some annotated text */ data legend_anno; length function $8 style color $ 12 text $50; xsys='3'; ysys='3'; hsys='3'; function='label'; position='4'; x=71.3; y=77.9; text='Three Times U.S. Rate'; output; y=y-2.5; text='Two Times U.S. Rate'; output; y=y-2.5; text='U.S. Rate (13.2)'; output; y=y-2.5; text='No Change'; output; run; data legend_anno; set legend_anno; output; function='move'; output; function='draw'; color='gray99'; x+2.5; size=.01; output; function='pie'; color='black'; size=.20; rotate=360; style='psolid'; output; run; data gif_anno; length function $8 style $20 imgpath $20 text $100 html $100; xsys='3'; ysys='3'; hsys='3'; position='5'; when='a'; function='move'; x=16; y=2.5; output; function='image'; imgpath='uscensusbureau.gif'; style='fit'; html='href="http://www.census.gov"'; x=x+24; y=y+4.25; output; run; /* Create an annotated 'shadow' to go behind the map. It's ok to use the already-projected map for this. */ data anno_shadow; set my_us; orig_order+1; run; proc sort data=anno_shadow out=anno_shadow; by state segment orig_order; run; proc gremove data=anno_shadow out=anno_shadow; by state; id state; run; data anno_shadow; length COLOR FUNCTION $ 8; retain FX FY FUNCTION; set anno_shadow; by state segment; xsys='2'; ysys='2'; color='gray88'; size=1.75; when='B'; style='msolid'; if first.segment then do; FUNCTION = 'poly'; FX = X; FY = Y; end; else if FUNCTION ^= ' ' then do; if X = . then do; X = FX; Y = FY; output; FUNCTION = ' '; end; else FUNCTION = 'polycont'; end; if FUNCTION ^= ' ' then do; output; if last.segment then do; X = FX; Y = FY; output; end; end; run; /* Give a little x & y offset, so it will look like a shadow */ data anno_shadow; set anno_shadow; x=x+.0016; y=y-.0024; run; /* Combine all the annotate datasets */ data all_anno; set state_anno title_anno box_anno legend_anno gif_anno anno_shadow ; run; goptions xpixels=900 ypixels=700; goptions gunit=pct ftext="arial" htext=1.75; goptions device=png; goptions cback=white noborder; ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" (title="Percent Change in Resident Population (SAS/Graph gmap)") style=minimal; pattern1 v=solid c=cx006837; pattern2 v=solid c=cx31a354; pattern3 v=solid c=cx78c679; pattern4 v=solid c=cxc2e699; pattern5 v=solid c=cxffffcc; legend1 across=1 mode=share position=(top right) offset=(-11,-16) shape=bar(3,2.0) label=(position=top font="arial/bold" 'Percent Change'); title1 a=-90 h=3 " "; /* Finally, draw the heavily customized & annotates map */ proc gmap data=mydata map=my_us all anno=all_anno; id st; choro color_bin / coutline=gray99 legend=legend1 discrete html=myhtmlvar des="" name="&name"; run; quit; ODS HTML CLOSE; ODS LISTING;