I am trying to add a legend to my plot that does not exactly match the data that I am plotting. Sorry for the lengthy code, but I wanted you to have all my information. I am probably giving more than is needed. Simply put, I want to color code the plotting markers, but I only want 1 black marker to appear in the legend with a set label.
proc format;
value posneg
1='Positive'
2='Negative'
9='Non-Evaluable';
run;
data waterfall;
input SUBJECT LESID POSNEG BESTPCT @@;
format posneg posneg. bestpct percent9.2;
cards;
1010 1 1 -0.269 1020 1 1 -0.235
1020 2 1 -0.043 1020 3 1 -0.167
1020 4 1 -0.03 1050 1 9 0.077
1060 1 9 . 1060 2 1 -0.25
1060 3 2 -0.059 1060 4 1 -0.111
1060 5 1 -0.24 1070 1 2 0
1080 1 1 . 1080 2 2 .
1080 3 1 . 1080 4 1 .
1090 1 1 -0.125 1110 1 1 0.179
1110 2 1 -0.056 1120 1 2 0
1120 2 2 -0.211 4010 1 2 -0.022
4010 2 2 1.344 2010 1 9 0.462
2020 1 1 0.217 2030 1 1 0.4
2030 2 1 0.174 2040 1 1 0.091
2040 2 1 0.1 2050 1 9 0.2
2050 2 1 0.917 2060 1 1 .
2060 2 1 . 2060 3 1 .
2060 4 1 . 2060 5 1 .
;
run;
proc sort data=waterfall;
by posneg descending bestpct;
run;
data waterfall;
set waterfall;
n=_n_;
if bestpct=. then scattermissing=0;
label scattermissing='No Post-Baseline Assessment';
run;
/* Determine the range and tick values of the y-axis for plotting */
data tickvalues;
do VALUE=-1 to &yaxismax. by 0.2;
output;
end;
format value 5.1;
run;
proc sql noprint;
select value into :tickvaluelist separated by ' ' from tickvalues;
select (ceil(max(&yvar.)/0.2))*0.2 into :yaxismax from waterfall;
quit;
I want the plot to look like this one (X's color coded based on POSNEG):
proc template;
define statgraph barscatter;
begingraph;
entrytitle 'Best Percent Change in Lesion Size';
layout overlay / xaxisopts=(display=none) yaxisopts=(label="&ylab." linearopts=(viewmin=-1.05 viewmax=%sysevalf(&yaxismax.+.05) tickvaluelist=(&tickvaluelist.)));
barchart x=n y=bestpct / group=posneg name='b';
scatterplot x=n y=scattermissing / group=posneg markerattrs=(symbol=X) name='s';
referenceline y=eval(coln(0.2, -0.3)) / lineattrs=(color=black pattern=dot);
discretelegend 'b' 's' / across=1 autoalign=(bottomleft) location=inside;
endlayout;
endgraph;
end;
run;
proc sgrender data=waterfall template=barscatter;
run;
But I want the legend to look like this one (only 1 black marker for SCATTERMISSING with the "No Post-Baseline Assessment" label):
proc template;
define statgraph barscatter;
begingraph;
entrytitle 'Best Percent Change in Lesion Size';
layout overlay / xaxisopts=(display=none) yaxisopts=(label="&ylab." linearopts=(viewmin=-1.05 viewmax=%sysevalf(&yaxismax.+.05) tickvaluelist=(&tickvaluelist.)));
barchart x=n y=bestpct / group=posneg name='b';
scatterplot x=n y=scattermissing / markerattrs=(symbol=X) name='s';
referenceline y=eval(coln(0.2, -0.3)) / lineattrs=(color=black pattern=dot);
discretelegend 'b' 's' / across=1 autoalign=(bottomleft) location=inside;
endlayout;
endgraph;
end;
run;
proc sgrender data=waterfall template=barscatter;
run;
Since you have 9.3, you might be able to use the LEGENDITEM statement to define the legend entry without having to define the additional scatter. Here is an example:
proc template;
define statgraph custom;
beginGraph;
legendItem type=marker name='markerItem' / label='Custom Marker' markerattrs=(color=black symbol=circle) labelattrs=black;
layout overlay;
scatterPlot x=weight y=height / group=sex markerattrs=(symbol=circle);
discreteLegend 'markerItem';
endLayout;
endGraph;
end;
run;
proc sgrender data=sashelp.class template=custom; run;
Have a look below. Only mention the scatterplot name in the discretelegend statement and use the legendlabel option for the text of the legend label
This is almost identical to the second PROC TEMPLATE I had. It does put just a single black X in the legend, but the X's on the plot are also black. I am trying to keep the legend the way you provided it but still have the X's to stay color coded like the bars by the POSNEG variable.
What version of SAS are you running?
I'm using SAS 9.3.
I did something like this for the survival plot in this article: http://blogs.sas.com/content/graphicallyspeaking/2014/02/09/survival-plot/
Here, I have drawn the censored markers using non-grouped scatter plot (in black), and overlaid the same with a grouped scatter plot resulting in colored markers. Now, only the colored markers are visible in the plot. However, I have included the non-grouped scatter plot in the legend.
Could you use a similar idea?
Thank you, Sanjay! I had tried something similar to this before, but when I overlaid the color on top of the black, it almost looked like the X's had been bolded. I tried it again, and it wasn't too bad. I think it was because I didn't specify an exact black color but rather used a default lighter black (dark gray or sorts).
Since you have 9.3, you might be able to use the LEGENDITEM statement to define the legend entry without having to define the additional scatter. Here is an example:
proc template;
define statgraph custom;
beginGraph;
legendItem type=marker name='markerItem' / label='Custom Marker' markerattrs=(color=black symbol=circle) labelattrs=black;
layout overlay;
scatterPlot x=weight y=height / group=sex markerattrs=(symbol=circle);
discreteLegend 'markerItem';
endLayout;
endGraph;
end;
run;
proc sgrender data=sashelp.class template=custom; run;
Yes, overplotting markers can make them look bolder due to the anti-aliasing. To avoid that, a trick I have used before is to plot the points you don't want to see somewhere outside the graph range (and set x and y axis ranges to show only the range you need). You will need another column for that. Now, there is no overplotting of the markers.
Or, you can set x or y for this column as missing...but an entire column cannot be missing. If it is, the plot will be thrown out. Dan's suggestion will work too.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.