BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Anita_n
Pyrite | Level 9

Dear all,

 

I have this code and I wish to shade the backgroud of plot indicating the normal and critical  areas. 

data have;
infile datalines;
input type $10. num_pat num_centers 3.;

datalines;
liver       8  6
stomach     4  6
breast     20  10
ovary      15  8
kidney     18  10
leucemia   16  2
intestine  4   2
CNS        5   1
lung      14   7
uterus    16   8
;

run;

data have;
set have;
r_value=num_pat/num_centers;

if r_value < 2 then grup="critical";else grup="normal";
if grup="normal" then high=.; else if grup="critical" then high=1.99;

label r_value= R-Values;
run;

proc sort data=have;
by descending r_value;
run;


proc sgplot data=have noautolegend ;
styleattrs datacolors=('CX5F9EA0' 'CX00FFFF' ) datacontrastcolors=('CX5F9EA0' 'CX00FFFF' );
label;

vbar type /response= num_centers  missing baselineattrs=(thickness=0) legendlabel='Number of treatment centers' name='a';

vbar type /response= num_pat missing baselineattrs=(thickness=0) barwidth=0.5 legendlabel='Number of patients' name='b'; 

xaxis type=discrete discreteorder=data display=(nolabel) valueattrs=(size=6pt family=arial);

yaxis  display=(nolabel) valueattrs=(size=7pt family=arial) grid;
y2axis  labelattrs=(size=8pt family=arial color=dimgray) valueattrs=(size=7pt family=arial);

vline type / response=r_value y2axis lineattrs=(color=gold  pattern=solid thickness=2) nostatlabel  legendlabel='R-values' name='c';

keylegend 'a' 'b' 'c' / location=outside position=bottom across=0 title="" valueattrs=(size=7pt family=arial) outerpad=(top=0.2cm) noborder;

run;

something like this:

Anita_n_0-1658919971564.png

how do I do that?

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hello @Anita_n,

 

You could add the WALLCOLOR= option to your STYLEATTRS statement to define the color of the "normal" area and add one or two VBAR statements to draw the "critical" area (using a constant variable).

data want;
set have;
critlimit=2;
label critlimit='R-Values';
run;

proc sgplot data=want noautolegend ;
styleattrs datacolors=('CX5F9EA0' 'CX00FFFF') datacontrastcolors=('CX5F9EA0' 'CX00FFFF') wallcolor=lightgrey;
label;
vbar type /response= critlimit nooutline barwidth=1 fillattrs=(color=lightpink) y2axis discreteoffset=-0.1;
vbar type /response= critlimit nooutline barwidth=1 fillattrs=(color=lightpink) y2axis discreteoffset= 0.1;

vbar type /response= num_centers fillattrs=(color='CX5F9EA0') missing baselineattrs=(thickness=0) legendlabel='Number of treatment centers' name='a';

vbar type /response= num_pat fillattrs=(color='CX00FFFF') missing baselineattrs=(thickness=0) barwidth=0.5 legendlabel='Number of patients' name='b'; 

xaxis type=discrete discreteorder=data display=(nolabel) valueattrs=(size=6pt family=arial);

yaxis  display=(nolabel) valueattrs=(size=7pt family=arial) grid offsetmin=0;
y2axis  labelattrs=(size=8pt family=arial color=dimgray) valueattrs=(size=7pt family=arial) min=0.66667;

vline type / response=r_value y2axis lineattrs=(color=gold  pattern=solid thickness=2) nostatlabel  legendlabel='R-values' name='c';

keylegend 'a' 'b' 'c' / location=outside position=bottom across=0 title="" valueattrs=(size=7pt family=arial) outerpad=(top=0.2cm) noborder;
run;

(I had to add the FILLATTRS= and MIN= options to existing statements because of interactions with the new VBAR statements. The OFFSETMIN=0 option avoids a margin of background color below the bars.)

View solution in original post

10 REPLIES 10
ballardw
Super User

Define "critical area" for your plot, which is two overlayed VBAR plots and has nothing in common with the "example" picture.

 

An axis for a continuous variable can be defined with ranges in data and overlay any of a number of things. But your xaxis for VBAR is categorical and so you are going to have some fun defining a range of the xaxis values.

Anita_n
Pyrite | Level 9
so, it's not possible to define ranges for categorial axis, is that right?
FreelanceReinh
Jade | Level 19

Hello @Anita_n,

 

You could add the WALLCOLOR= option to your STYLEATTRS statement to define the color of the "normal" area and add one or two VBAR statements to draw the "critical" area (using a constant variable).

data want;
set have;
critlimit=2;
label critlimit='R-Values';
run;

proc sgplot data=want noautolegend ;
styleattrs datacolors=('CX5F9EA0' 'CX00FFFF') datacontrastcolors=('CX5F9EA0' 'CX00FFFF') wallcolor=lightgrey;
label;
vbar type /response= critlimit nooutline barwidth=1 fillattrs=(color=lightpink) y2axis discreteoffset=-0.1;
vbar type /response= critlimit nooutline barwidth=1 fillattrs=(color=lightpink) y2axis discreteoffset= 0.1;

vbar type /response= num_centers fillattrs=(color='CX5F9EA0') missing baselineattrs=(thickness=0) legendlabel='Number of treatment centers' name='a';

vbar type /response= num_pat fillattrs=(color='CX00FFFF') missing baselineattrs=(thickness=0) barwidth=0.5 legendlabel='Number of patients' name='b'; 

xaxis type=discrete discreteorder=data display=(nolabel) valueattrs=(size=6pt family=arial);

yaxis  display=(nolabel) valueattrs=(size=7pt family=arial) grid offsetmin=0;
y2axis  labelattrs=(size=8pt family=arial color=dimgray) valueattrs=(size=7pt family=arial) min=0.66667;

vline type / response=r_value y2axis lineattrs=(color=gold  pattern=solid thickness=2) nostatlabel  legendlabel='R-values' name='c';

keylegend 'a' 'b' 'c' / location=outside position=bottom across=0 title="" valueattrs=(size=7pt family=arial) outerpad=(top=0.2cm) noborder;
run;

(I had to add the FILLATTRS= and MIN= options to existing statements because of interactions with the new VBAR statements. The OFFSETMIN=0 option avoids a margin of background color below the bars.)

Anita_n
Pyrite | Level 9

Thanks to you all for your suggestions

@FreelanceReinh : I adjusted your code this way:

 

data want;
set have;
if high ^=. then critlimit=35;
run;

proc sgplot data=want noautolegend ;
styleattrs datacolors=('CX5F9EA0' 'CX00FFFF') datacontrastcolors=('CX5F9EA0' 'CX00FFFF') wallcolor=dimgrey;
label;
vbar type /response= critlimit nooutline barwidth=1 fillattrs=(color=lightpink) y2axis discreteoffset=-0.1;
vbar type /response= critlimit nooutline barwidth=1 fillattrs=(color=lightpink) y2axis discreteoffset= 0.1;

vbar type /response= num_centers fillattrs=(color='CX5F9EA0') missing baselineattrs=(thickness=0) legendlabel='Number of treatment centers' name='a';
vbar type /response= num_pat fillattrs=(color='CX00FFFF') missing baselineattrs=(thickness=0) barwidth=0.5 legendlabel='Number of patients' name='b'; 

xaxis type=discrete discreteorder=data display=(nolabel) valueattrs=(size=6pt family=arial);

yaxis  display=(nolabel) valueattrs=(size=7pt family=arial) grid offsetmin=0;
y2axis  labelattrs=(size=8pt family=arial color=dimgray) valueattrs=(size=7pt family=arial) min=0.66667;

vline type / response=r_value y2axis lineattrs=(color=gold  pattern=solid thickness=2) nostatlabel  legendlabel='R-values' name='c';

inset "critical areas" / position=NE textattrs=(color=red family=arial size=7pt weight=bold);
inset "normal areas" / position=NW textattrs=(color=black family=arial size=7pt weight=bold);

keylegend 'a' 'b' 'c' / location=outside position=bottom across=0 title="" valueattrs=(size=7pt family=arial) outerpad=(top=0.2cm) noborder;
run;

I don't know if it make sense to do it this way but it seems to produce what I want

FreelanceReinh
Jade | Level 19

@Anita_n wrote:

I don't know if it make sense to do it this way but it seems to produce what I want


Great that it produces what you want. (But did you notice the change of the y2-axis label?)

 

My interpretation of

if r_value < 2 then grup="critical";else grup="normal";

was that the "critical" area was a horizontal stripe (unlike in the picture you posted) with upper limit r_value=2. If I had realized that it was really meant to be vertical, I would have suggested a BLOCK statement (as DanH_sas did) because I produced those block plots in the past.

Anita_n
Pyrite | Level 9

@FreelanceReinh yes , you right. that is the right defination for the critical and normal areas but I want the background to start from 0 to the maximum y2axis value (that is why I am asking if there is a better way to do that). I will can also try @DanH_sas  suggestion but at the moment your code worked for me, thanks.

DanH_sas
SAS Super FREQ

In this case, you might want to use a SERIES plot instead of a VLINE, unless you need the data summarized. For the background, you just need BLOCK plot. Here is a simple example:

 

data air;
set sashelp.air;
if (date <= '01jan1958'd) then period="earlier";
else period="later";
run;

proc sgplot data=air;
block x=date block=period / filltype=alternate;
series x=date y=air;
run;

Screen Shot 2022-07-27 at 9.44.49 AM.png

DanH_sas
SAS Super FREQ

Sorry, I just realized that your code also has VBARs in it. What I would do is use PROC SUMMARY or PROC MEANS to summarize the data. Then, use VBARPARMs and a SERIES instead so that I can put a BLOCK plot behind it, like in the example in my previous post.

Anita_n
Pyrite | Level 9

@DanH_sas the Vbarparm statement in combination with series and block statement is a very efficient way of solving this problem. I like that😊. Thankyou all for the help

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 10 replies
  • 2283 views
  • 6 likes
  • 5 in conversation