BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
djbateman
Lapis Lazuli | Level 10

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;

1 ACCEPTED SOLUTION

Accepted Solutions
DanH_sas
SAS Super FREQ

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;

View solution in original post

8 REPLIES 8
BrunoMueller
SAS Super FREQ

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

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 color=cx000000)
         
name='s'
         
legendlabel='No Post-Baseline Assessment'
        ;
        referenceline y=eval(coln(0.2, -0.3)) / lineattrs=(color=black pattern=dot);
        discretelegend  's' / across=1
         
autoalign=(bottomleft) location=inside;
      endlayout;
   
endgraph;
 
end;
run;
djbateman
Lapis Lazuli | Level 10

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.

DanH_sas
SAS Super FREQ

What version of SAS are you running?

djbateman
Lapis Lazuli | Level 10

I'm using SAS 9.3.

Jay54
Meteorite | Level 14

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?

djbateman
Lapis Lazuli | Level 10

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).

DanH_sas
SAS Super FREQ

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;

Jay54
Meteorite | Level 14

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.

SAS Innovate 2025: Call for Content

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!

Submit your idea!

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
  • 8 replies
  • 2119 views
  • 6 likes
  • 4 in conversation