Maps Online >Resources SAS logo
Feedback   

Sample Data
Sample Programs
Tools
Useful Links

/*******************************************************************\
| Copyright (C) 2005 by SAS Institute Inc., Cary, NC, USA.          |
|                                                                   |
| SAS (R) is a registered trademark of SAS Institute Inc.           |
|                                                                   |
| SAS Institute does not assume responsibility for the accuracy of  |
| any material presented in this file.                              |
\*******************************************************************/

/********************************************************************
* Plot Geocoded Points with PROC GMAP                              *
* Example 5 from SUGI 30 Presentation:                             *
*    "Cheap Geocoding: SAS/GIS and Free TIGER Data"                *
********************************************************************/

/********************************************************************
* Set location and libref for data and html map page.              *
********************************************************************/
%let PATH=C:\Temp;
libname CENTROID "&PATH";

/********************************************************************
* Create a customer address data set.                              *
********************************************************************/
data CENTROID.CUSTOMERS (label = 'Customer Addresses');
input address   $ 1-22          /* House address (not used)      */
name      $ 24-48         /* Customer name                 */
city      $ 49-63         /* City name (not used)          */
statecode $ 64-65         /* State abbreviation (not used) */
zip                       /* Customer ZIP Code (numeric)   */
revenue;                  /* Total revenue for customer    */
format revenue dollar9.0;       /* Show revenue in dollars       */
label  revenue = 'Revenue';     /* Label to appear on map legend */
cust_ID = _n_;                  /* Assign customer ID number     */
cards;
123  E. Wine Street    J. Cheever Loophole      Mullins        SC 29574 985.33
611  Jackson Street    Cuthbert J. Twillie      Vidalia        GA 30474 2533.25
300  North Odum Street Prof. Quincy Wagstaff    Pembroke       NC 28372 1899.45
5575 Peachtree Pkwy.   Kaspar Gutman            Norcross       GA 30022 33.44
1525 N. Shenandoah Ave Dr. Hugo Z. Hackenbush   Front Royal    VA 22630 987.02
2310 Cannon Bridge Rd  Charlie Allnut           Cordova        SC 29039 1459.65
305  Mill Creek Drive  Larson E. Whipsnade      Fuquay Varina  NC 27526 4566.98
1911 W. Main St.       Guillermo Ugarte         Richmond       VA 23220 17.45
2313 Dale Ave.         Dewey, Cheatem & Howe    Roanoke        VA 24013 989.20
7825 Old Middlesex Rd  Capt. Geoffrey Spaulding Bailey         NC 27807 1798.33
1935 E. Frederick St   Joel Cairo               Blacksburg     SC 29702 2566.45
900  Stony Landing Rd  Charles Blutoski         Easley         SC 29641 783.25
26   Ancho Street      Brigid O'Shaughnessy     Burlingame     CA 94000 543.99
1373 London Bridge Rd  Fred C. Dobbs            Virginia Beach VA 23451 898.25
626  Mohican Trail     Rufus T. Firefly         Wilmington     NC 28409 123.45
216  12th Street       Otis B. Driftwood        Lynchburg      VA 24504 98.56
35   W. Chatham Str    Elwood Blues             Pittsboro      NC 27312 661.13
100  W. Church Street  Duke Mantee              Cherryville    NC 28021 4531.87
;
run;

/********************************************************************
* Reorder customer data by ZIP for merging.                        *
********************************************************************/
proc sort data = CENTROID.CUSTOMERS;
by ZIP;
run;

/********************************************************************
* Assign ZIP centroid coordinates to customer addresses.           *
********************************************************************/
data CENTROID.CUSTOMERS (label = 'Customers Located by ZIP Centroid Geocoding')
CENTROID.MISSING   (label = 'Customers Not Found by ZIP');
merge CENTROID.CUSTOMERS (in=a)   /* Customer addresses          */
SASHELP.ZIPCODE;            /* ZIP and centroid X/Y data   */
by ZIP;                           /* ZIP is the linkage variable */
if a;                             /* Keep only customer obs      */

/*****************************************************************
* If this customer has a bad ZIP Code, set this obs aside.      *
*****************************************************************/
if X = . or Y = . then output CENTROID.MISSING;

/*****************************************************************
* Otherwise this customer's ZIP Code was found and has valid    *
* X/Y values.                                                   *
*****************************************************************/
else output CENTROID.CUSTOMERS;
run;

/********************************************************************
* Determine which states contain customers.  The base map data     *
* will be subset to display only these states.                     *
********************************************************************/
proc freq data = CENTROID.CUSTOMERS noprint;
tables state / out = _states_ (label = 'States containing customers');
run;

/********************************************************************
* Generate a where clause to subset the map data for only the      *
* states containing customers.  The clause is placed in the macro  *
* variable &CoverWhere for use below.                              *
********************************************************************/
data _NULL_;
set _STATES_ (rename = (state = curState)) end = last;
length  stateList $ 256;             /* States with customers    */
retain  stateList "";

/*****************************************************************
* If the first state, initialize the where clause string.       *
*****************************************************************/
if _n_ = 1 then stateList = trim(left(curState));

/*****************************************************************
* If not the first state, append it to the string.              *
*****************************************************************/
else stateList = compress(stateList || "," || curState);

/*****************************************************************
* If final state, put where clause string into macro variable.  *
*****************************************************************/
if last then do;
call symput( 'StateList', trim(stateList) );
end;
run;

/********************************************************************
* Use where clause to subset US map for states with customers.     *
********************************************************************/
data CENTROID.MAP;
set MAPS.STATES;                     /* Base map of US states    */
where state in (&stateList) &        /* List of states wanted    */
density < 3;                   /* Thin the point data      */
run;

/********************************************************************
* Create an ANNOTATE data set to draw stars at customer sites.     *
********************************************************************/
data CENTROID.ANNOTATE;                 /* Annotate data set        */
set CENTROID.CUSTOMERS;              /* Customer data with X/Y   */
length html $ 500                    /* Chart-tip text string    */
function style color $ 8;
xsys = '2';
ysys = '2';
hsys = '3';
when = 'A';

/*****************************************************************
* Convert decimal degrees to radians to match map data.         *
*****************************************************************/
x = -x * (atan(1)/45);
y =  y * (atan(1)/45);

/*****************************************************************
* Draw customer point marker with a star.                       *
*****************************************************************/
function = 'label';
style    = 'special';
text     = 'M';                      /* Use star symbol          */
color    = 'cx2e19dd';               /* Star color               */
size     = 5;                        /* Star height              */
position = '5';                      /* Center star at X/Y       */

/*****************************************************************
* Add chart-tip text for this point.  This information will be  *
* displayed when you hover over the customer point.             *
*****************************************************************/
html     = 'alt='|| quote(
'Name:       '||trim(left(name))||'0D'x||
'City:          '||trim(left(city))||', '||trim(left(statecode))||'0D'x||
'Revenue:  '||trim(left(put(revenue, dollar8.2)))||' ');
run;

/********************************************************************
* Combine map and annotate data sets.                              *
* They must be projected together.                                 *
********************************************************************/
data _COMBINED_;
set CENTROID.MAP CENTROID.ANNOTATE;
run;

/********************************************************************
* Project the map and annotate data.                               *
********************************************************************/
proc gproject data = _COMBINED_
out  = _COMBINED_;
id state;
run;

/********************************************************************
* Separate projected map and annotate into two data sets.          *
********************************************************************/
data CENTROID.MAP CENTROID.ANNOTATE;    /* Separate data sets       */
set _COMBINED_;                      /* Combined projected data  */
if density = . then
output CENTROID.ANNOTATE;        /* Points                   */
else
output CENTROID.MAP;             /* Base map                 */
run;

/********************************************************************
* Use SAS/GRAPH GMAP Procedure and ODS to create web page.         *
********************************************************************/
ods results off;
ods html  close;                        /* Start new ODS output     */
ods html  path="&PATH"                  /* Location of output file  */
body="Customers.html";        /* Output file name         */
goptions  reset=all                     /* Clear graphics settings  */
device=gif                    /* Output image type        */
cback=cxc3bdb6;               /* Map background color     */
pattern1  v=solid c=cxeeeee6 r=50;      /* State fill color         */
title1    h=2 f=centb "Customer Locations"; /* Map titles           */
title2    h=1.5 f=centbi "Geocoded by ZIP Centroid with SAS";
footnote1 h=1.3 j=l f=centb " Map by PROC GMAP";
footnote2 h=1.3 j=l f=centb " Hover to see point values";

/********************************************************************
* Generate the map.                                                *
********************************************************************/
proc gmap data = CENTROID.MAP           /* Response data set needed */
map  = CENTROID.MAP           /* Projected map data       */
anno = CENTROID.ANNOTATE;     /* Projected point data     */
id state;                            /* Map variable             */
choro state /                        /* Draw choropleth map      */
coutline = cx739436           /* State outline color      */
des      = "Customers"        /* grseg entry label        */
nolegend;                     /* Suppress legend          */
run;
quit;
ods listing close;                      /* End ODS output           */

/********************************************************************
* Open the map in your default browser.  Hover over the address    *
* points to see the customer information.                          *
********************************************************************/
dm 'wbrowse "&PATH\Customers.html"';