Date: Thu, 25 Feb 2010 08:43:30 -0800
Reply-To: Bill McKirgan <bill.mckirgan@GMAIL.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Bill McKirgan <bill.mckirgan@GMAIL.COM>
Organization: http://groups.google.com
Subject: Re: graph: fill area between series lines
Content-Type: text/plain; charset=ISO-8859-1
I just wanted to give you all an update on my graph problem and
solution. Below, is the code I used to make the kind of graph my
colleague 'TK' was asking for last week. He was using excel, and was
asked to fill in the area between two lines and found that while this
sounded easy-enough to do, it was in fact impossible with Excel 2007.
The closest we came was by overlaying area plots and adding borders to
the areas and making them transparent. I took a stab at the problem
with SGplot and with my limited SAS graph knowlege I ran into the same
problem (ie, there's no simple solution), and that's when I posted-up.
Thanks to all of you you expressed interest and offered ideas,
examples and spot-on solutions both on and off list. I am in your
debt and will look through these ideas later on as a way to learn more
about things like annotation datasets, and hash objects for making
more data-driven custom solutions.
In the end I used a solution provided by Mike Zdeb that is similar to
what Ya Huang posted. Another excellent candidate solution was Data
_NULL_'s which used hash objects to automate the part where fill areas
between the intersecting lines are trimmed. _NULL_, that stuff was
way over my head, but I will keep studying it because I want to learn
more techniques for making dynamic programs. I use list processing
and macro solutions in my regular data management work, but do not yet
understand the hash, and appreciate your example as it will probably
be what helps light the hash-object bulb in my head (so to speak).
I'm pretty sure my colleague will be very happy with the result, and
may be astounded to learn that it was accomplished by the generous
support of the SAS-L community.
Thanks!!
Bill McKirgan
Here's that code...
/* _graph_help__mike_zdeb_.sas
Use this to make a graph for TK.
This began as an excel file/graph with a request
to fill the areas between the two plotted lines.
Not easy/possible to do in excel Bill McKirgan
tried to do in SAS sgplot and then asked for help
on the SAS Listerv:
http://groups.google.com/group/comp.soft-sys.sas/browse_thread/thread/c08750954d3fea12?hl=en&pli=1
Many good ideas were suggested, and Mike Zdeb's solution
was the best/closest to meeting the goal TK described.
Mike's code was downloaded from SAS-L and into this
program which has some minor modifications to improve
colors, add titles and graph legend information.
Bill McKirgan
2/25/2010
*/
/* point to directory to save output */
%let whatpath=mypath;
/* Mike uses formatted variable instead of character data */
proc format;
value age
1 = '<20'
2 = '20-24'
3 = '25-29'
4 = '30-34'
5 = '35-39'
6 = '40-44'
7 = '45-49'
8 = '50-54'
9 = '55-59'
10= '60-64'
11= '65-69'
12= '70-74'
13= '75-79'
14= '80-84'
15= '85+'
;
run;
/* Admin Data from TK's chart (deidentified prior to posting to SAS-
L)*/
data foo;
input y1 y2 @@;
* set y3 to the lower of the two values;
y3 = y1*(y1 le y2) + y2*(y2 lt y1);
x + 1;
datalines;
.00 .00
.01 .00
.03 .01
.04 .01
.05 .02
.06 .04
.08 .06
.08 .09
.09 .16
.15 .29
.10 .15
.08 .08
.09 .06
.07 .03
.06 .02
;
run;
* Mike's HARDCODE where the lines cross between X=7 and X=8;
/* This was brilliant, and another similar post from Data _Null_
involved
a dynamic solution to filling the areas that involved
many lines of code and the use of HASH objects
That too was very close to the desired final appearance;
however, the hashes were way beyond my comprehension
but I will study the example because I like
data-driven solutions
*/
data foo;
if last then do;
x = 7.655;
y3 = 0.08;
call missing (y1,y2);
output;
end;
set foo end=last;
output;
run;
proc sort data=foo;
by x;
run;
goptions reset=all gunit=pct htext=2;
/* McKirgan edits to fine-tune graph output (suppress lines for clean
legend)
Add color to lines and fill patterns */
symbol1 i=j c=white; /* keep lines white to suppress in legend */
symbol2 i=j c=white; /* keep lines white to suppress in legend */
symbol3 i=j c=white; /* keep lines white to suppress in legend */
symbol4 i=j f=marker v='V' c=red; /* line color */
symbol5 i=j f=marker v='W' c=blue;
pattern1 v=s c=white;
pattern2 v=s c=lightblue ;
pattern3 v=s c=lightgreen ;
axis1 label=(a=90 'PERCENTAGE IN COHORT')
order=0 to 0.3 by 0.05
minor=(n=4)
;
axis2 label=('AGE GROUP')
offset=(0,0)pct
minor=none
;
legend1 label=none
value=('' '' '' 'MyHVs' 'Total Vs')
down=5
mode=protect
position=inside
;
title1 ls=1 'MHV vs Total V Age Distribution' ;
*title2 a=90 ls=1 'title 2' ;
*title3 a=-90 ls=1 'title 3' ;
*footnote1 ls=1 'footnote 1' ;
/* pdf is okay, but simply right clicking graph in SAS
and exporting as JPG is faster and has a better
result (an image that can be copy/pasted into
an MS-Office Word/Powerpoint file */
/* suppressing output to pdf after initial test */
*ods pdf file="&WHATPATH.\MHv_graph.pdf";
/* JUST EXPORT THE GRAPH FROM WITHIN SAS SESSION */
proc gplot data=foo;
plot (y3 y2 y1 y2 y1) * x
/overlay
areas=3
vaxis=axis1
haxis=axis2
legend = legend1 ;
format x age.;
run;
quit;
*ods pdf close;
run;
quit;