BookmarkSubscribeRSS Feed
BenConner
Pyrite | Level 9

Hi,

 

I'm trying to represent a subset of counties but need to have both couny labels & outlines as well as a state outline.  I haven't been able to come up with the state-level boundary annotate file that would work.  

 

What I have so far is:

 

data ohiomap;
  set mapsgfk.us_counties(where=(statecode='OH'));
run;


%annomac;

%centroid(ohiomap,centroids,state county);

proc sql;
create table anno_centroids as
   select a.*, trim(left(b.idname)) as text,
         '2' as xsys, '2' as ysys, '3' as hsys, 'a' as when, 'label' as function,
        '5' as position, 2 as size, 'black' as color
    from centroids a left join mapsgfk.us_counties_attr b
   on a.state = b.state and a.county = b.county;

 

create table ohiodata as
    select distinct county, 39 as state
   from anno_centroids
   where text like 'A%';
run;
quit;


pattern1 v=s c=white;

 

proc gmap data=ohiodata map=ohiomap;* anno=anno_state;
   id state county;
   choro state / levels=1 nolegend anno=anno_centroids(where=(text=:'A'));
run;
quit;

 

This gives me counties that start with 'A' but I also need the state outline.  If I use the 'all' keyword on the gmap statement, that works but includes all county boundaries, which I don't need.  I've tried several approaches to generating the anno_state file but haven't gotten it right yet.  

 

Thanks!

 

--Ben

4 REPLIES 4
ballardw
Super User

The basic approach is to get a map data set of the boundary points you want. Since you want to have county, or combinations thereof, start with a county map subsetted to the state of interest. It sounds like already have that.

 

Then use Proc Gremove to create a new map set with the internal (county) boundaries removed. There is an example in the online help for creating districts from the US State map data.

After you create a boundary set that maps successfully then you trace boundaries to create an annotate set. Here's an example from a project I did.

data distanno;
   length function color $8;
   retain xsys ysys '2' when 'a' color 'black' size 2 xsave ysave;
   drop xsave ysave;
   set idmap.districtmap ;
   by district segment;
  /* Move to the first coordinate */
   if first.segment then do;
      function='move';
      xsave=x;
      ysave=y;
      output;
   end;
  /* Draw to each successive coordinate */
  else do;
    function='draw';
    line=1 ; 
    output;

    /* Connect the last coordinate to the first */
    if last.segment then do;
      x=xsave;
      y=ysave;
      output;
    end;
  end;
run;

This uses an input map that has already combined counties into districts in my state and then creates a boundary annotate set to outline them. The trace the boundary approach should work for any map boundary set. If the map data when sorted doesn't display correctly you might try the BY with the notsorted option.

 

 

A key part of this is to start with a relatively high resolution base county set and use that for to make all of the annotates from that so that you don't get odd artifacts when you use county, county groups, and/or state boundaries together.

BenConner
Pyrite | Level 9

Good morning,

 

I added the following prior to the proc gmap call:

 

proc gremove data=ohiomap out=stateonly;
  by state;
  id county;
run;

data anno_state;
  set stateonly;
  by segment;
  length function $8 color $8;
  if first.segment then function='poly'; else function='polycont';
  color='black'; style='mempty'; when='b'; xsys='2'; ysys='2'; line=3; size=1;
run;

 

data map;

  set ohiomap stateonly;

run;

 

And then added that to the proc gmap call per:

 

proc gmap data=ohiodata map=map anno=anno_state;

 

That gave me the map I was looking for (state boundary with dashed lines and labeled county boundaries).  

 

I'm now getting a bunch of:

 

NOTE: PROBLEM IN OBSERVATION 1 -
   DATA SYSTEM REQUESTED, BUT VALUE IS NOT ON GRAPH 'X'
NOTE: PROBLEM IN OBSERVATION 2 -
   DATA SYSTEM REQUESTED, BUT VALUE IS NOT ON GRAPH 'X'
NOTE: PROBLEM IN OBSERVATION 3 -
   DATA SYSTEM REQUESTED, BUT VALUE IS NOT ON GRAPH 'X'

 

This is referring to the anno_state file.  The x value in Obs 1 is 25827.864786.  I see 2 observations with that value: one with a county FIPS code and one with it missing from the state boundary file.  So I'm not sure why these are getting flagged. ?

 

--Ben

ballardw
Super User

You don't want to add the annotate set back to the MAP data. Annotate is to add to an existing graphics output. The variables on the records for the Annotate set would likely

 

Try

proc gmap data=ohiodata map=ohipmap anno=anno_state;

 

I think you may want the WHEN in you state to be 'A'. Gmap doesn't really do transparencies (or I haven't tried lately any way) and if you have 'B' then the state boundary will be drawn before the Map and data and overwritten. 'A' adds it after the county level map is drawn.

 

BenConner
Pyrite | Level 9

Was able to get this put together eventually, using:

proc gmap data=ohiodata map=map all anno=anno_state;

  id county;

  choro ptbpct / discrete legend=legend1 anno=anno_centroids(where=(county in (&county))) xsize=4.75in;

  format ptbpct pctlabels.;

  label ptbpct='Map Measure Ranges';

run;

quit;

 

The map file did need the state outline boundary added to it to suppress errors in the log similar to:

DATA SYSTEM REQUESTED, BUT VALUE IS NOT ON GRAPH 'Y'

And the resulting map had the bottom portion of the state outline truncated. 

 

Normally the 'B' value for the when variable would indeed result in the lines being covered; in this case though they were outside the polygons being drawn in most cases, and where the county boundaries and state boundary were identical, the user wanted to see the solid county boundary. 

 

Thanks for the guidance on this one!  At times simple things just aren't as obvious as it would appear.

 

--Ben

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 1087 views
  • 0 likes
  • 2 in conversation