Hey All,
I'm producing a 'butterfly graph' by-clinic, using code very like the below. My problem is that for clinics where all the providers have 0s for one of the stats I'm reporting, SAS is putting 0 smack dab in the middle of the x-axis, which looks really weird (please see attachment SGRender3.png, or run the below code to see what I'm talking about).
The easiest way I can think of to fix this would be to specify min and max values for the x-axes. But I don't want to do that because the real data varies considerably by clinic, and there's no single max value I can use for every clinic that doesn't compress the provider-by-provider variation all to heck at some large proportion of the clinics.
I asked this question on SAS-L and Joe Matise (god bless 'im) suggested coming and asking here.
Is there some good way to keep SAS from letting that 0-value float into the center of my x-axes?
Many thanks!
-Roy
data psa_percents ;
input
@1 clinic $char5.
@7 provider $char15.
@25 num_males75 3.0
@29 pct_overpsa 5.1
;
datalines ;
north Banderas, Antonio 80 15.2
north Jolie, Angelina 45 75.5
north Bale, Christian 130 30
west Claus, Santa 225 0
west Bunny, Easter 340 0
west Cruz, Ted 89 0
run ;
proc template ;
define statgraph psa_butterfly ;
begingraph ;
layout lattice _id='lattice' / columndatarange = data
columngutter = 0
rowdatarange = data
rowgutter = 10
/* columnweights = (0.62 0.38) */
columns = 2 ;
layout overlay _id='overlay' / yaxisopts = (gridattrs=(color=CXE8E6E8 pattern=SOLID thickness=1 )
gridDisplay = on
display =(LINE TICKVALUES TICKS))
xaxisopts = (label = '# PSAs 75+'
reverse = true
type = linear
gridDisplay = on ) ;
barchart _id='bar2' x=PROVIDER y=num_males75 / name='bar2' orient = horizontal ;
endlayout;
layout overlay _id='overlay2' / yaxisopts=(gridattrs=(color=CXE8E6E8 pattern=SOLID thickness=1 )
gridDisplay=on
display=(LINE ))
xaxisopts=(label="Percent of 75+ males in panel having PSA"
type=linear
gridDisplay = on
);
barchart _id='bar' x=PROVIDER y= pct_overpsa / name='bar' orient = horizontal ;
endlayout;
endlayout;
endgraph;
end;
options orientation = landscape ;
ods html path = "c:\temp" (URL=NONE)
body = "deleteme.html"
(title = "Axis Problems")
;
proc sgrender data= psa_percents template = psa_butterfly ;
by clinic ;
run;
ods _all_ close ;
Ah, that does the trick. Many thanks Sanjay!
Here's what I came up with:
data psa_percents ; input @1 clinic $char5. @7 provider $char15. @25 num_males75 3.0 @29 pct_overpsa 5.1 @35 dummy 1.0 ; datalines ; north Banderas, Antonio 80 15.2 1 north Jolie, Angelina 45 75.5 1 north Bale, Christian 130 30 1 west Claus, Santa 225 0 1 west Bunny, Easter 340 0 1 west Cruz, Ted 89 0 1 ; run ; proc template ; define statgraph psa_butterfly ; begingraph ; layout lattice _id='lattice' / columndatarange = data columngutter = 0 rowdatarange = data rowgutter = 10 /* columnweights = (0.62 0.38) */ columns = 2 ; layout overlay _id='overlay' / yaxisopts = (gridattrs=(color=CXE8E6E8 pattern=SOLID thickness=1 ) gridDisplay = on display =(LINE TICKVALUES TICKS)) xaxisopts = (label = '# PSAs 75+' reverse = true type = linear gridDisplay = on ) ; barchart _id='bar2' x=PROVIDER y=num_males75 / name='bar2' orient = horizontal ; endlayout; layout overlay _id='overlay2' / yaxisopts=(gridattrs=(color=CXE8E6E8 pattern=SOLID thickness=1 ) gridDisplay=on display=(LINE )) y2axisopts = (display = none) xaxisopts=(label="Percent of 75+ males in panel having PSA" type=linear gridDisplay = on ); barchart _id='bar' x=PROVIDER y= pct_overpsa / name='bar' orient = horizontal ; scatterplot _id = 'scat' x = dummy y = dummy / yaxis = y2 datatransparency = 1 ; endlayout; endlayout; endgraph; end; options orientation = landscape ; ods html path = "c:\temp" (URL=NONE) body = "deleteme.html" (title = "Axis Problems") ; proc print ; run ; proc sgrender data= psa_percents template = psa_butterfly ; by clinic ; run; ods _all_ close ;
When you have only one value on a numeric axis, it will be placed in the middle of the axis. If you have some data range, you will get a regular axis. One way is to ensure at least a couple of value (say 0 and 1) by overlaying a dummy scatter plot with transparent markers. Use the data range appropriate to your plot.
Ah, that does the trick. Many thanks Sanjay!
Here's what I came up with:
data psa_percents ; input @1 clinic $char5. @7 provider $char15. @25 num_males75 3.0 @29 pct_overpsa 5.1 @35 dummy 1.0 ; datalines ; north Banderas, Antonio 80 15.2 1 north Jolie, Angelina 45 75.5 1 north Bale, Christian 130 30 1 west Claus, Santa 225 0 1 west Bunny, Easter 340 0 1 west Cruz, Ted 89 0 1 ; run ; proc template ; define statgraph psa_butterfly ; begingraph ; layout lattice _id='lattice' / columndatarange = data columngutter = 0 rowdatarange = data rowgutter = 10 /* columnweights = (0.62 0.38) */ columns = 2 ; layout overlay _id='overlay' / yaxisopts = (gridattrs=(color=CXE8E6E8 pattern=SOLID thickness=1 ) gridDisplay = on display =(LINE TICKVALUES TICKS)) xaxisopts = (label = '# PSAs 75+' reverse = true type = linear gridDisplay = on ) ; barchart _id='bar2' x=PROVIDER y=num_males75 / name='bar2' orient = horizontal ; endlayout; layout overlay _id='overlay2' / yaxisopts=(gridattrs=(color=CXE8E6E8 pattern=SOLID thickness=1 ) gridDisplay=on display=(LINE )) y2axisopts = (display = none) xaxisopts=(label="Percent of 75+ males in panel having PSA" type=linear gridDisplay = on ); barchart _id='bar' x=PROVIDER y= pct_overpsa / name='bar' orient = horizontal ; scatterplot _id = 'scat' x = dummy y = dummy / yaxis = y2 datatransparency = 1 ; endlayout; endlayout; endgraph; end; options orientation = landscape ; ods html path = "c:\temp" (URL=NONE) body = "deleteme.html" (title = "Axis Problems") ; proc print ; run ; proc sgrender data= psa_percents template = psa_butterfly ; by clinic ; run; ods _all_ close ;
In this particular case you could define a linearopts=(viewmax=100 viewmin=0) for the second graph. That seems reasonable (your percentage graph should probably be always going to 100 anyway). On the left side though perhaps that's not optimal. Are you trying to make these slides distinct (ie, they're not being shown together), or are they being shown together (in which case a single consistent axis min/max for each set of graphs is reasonable)?
If the latter, then you can use PROC MEANS or PROC SQL to determine a reasonable max for the whole set, and then define that using a MVAR or Dynamic (depending on how you want to pass it over). But you can't pass two for the graphs separately; in that case, Sanjay's solution of a transparent scatter plot is a good one as you can do that custom for each separate region.
Thanks for the reply!
Alas, the graphs are being shown separately, so I really want the x-axes to be scaled for each clinic (even the percentage one). I think the linearopts=(viewmax/min) option just lets me set a global min & max value that gets used accross all clinics.
Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.
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.
Ready to level-up your skills? Choose your own adventure.