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

How do I specify the LEGEND statement for these three lines (see code). to look like this Capture.PNG  but with CLVEF and CPGPRESV and in the box.    I made the legend in the picture with  mergedlegend "BNPPRONT" "BNPPRONT1";  

seriesplot x=xval  y=BNPPRONT  / name="BNPPRONT" lineattrs=(color=red pattern=dash) yaxis=y /*curvelabel='NTproBNP' curvelabelattrs=(color=red size=6pt)*/;       
scatterplot x=xval y=BNPPRONT  / name="BNPPRONT1" markerattrs=(color=red symbol=circle) yaxis=y datalabel=BNPPRONT datalabelattrs=(size=6pt);                     
                                                                                                                                                                  
seriesplot  x=xval y=CLVEF     / name="CLVEF"    lineattrs=(color=blue pattern=dash) yaxis=y2  /*curvelabel='LVEF' curvelabelattrs=(color=blue size=6pt)*/;       
scatterplot x=xval y=CLVEF     / name="CLVEF1"                markerattrs=(color=blue symbol=diamondfilled) yaxis=y2  datalabel=CLVEF datalabelattrs=(size=6pt);  
                                                                                                                                                                  
seriesplot  x=xval y=CPGPRESV  / name="CPGPRESV" lineattrs=(color=blue pattern=dash) yaxis=y2  /*curvelabel='LVOTG' curvelabelattrs=(color=blue size=6pt)*/;      
scatterplot x=xval y=CPGPRESV  / name="CPGPRESV1"                markerattrs=(color=blue symbol=diamond)  yaxis=y2 datalabel=CPGPRESV datalabelattrs=(size=6pt);  

   

1 ACCEPTED SOLUTION

Accepted Solutions
DanH_sas
SAS Super FREQ

Here is a simple example of what I was describing:

 

proc template;
    define statgraph merged;
    begingraph;
    layout overlay;
    seriesplot x=ageatstart y=systolic / name="a1" lineattrs=GraphData1;
    scatterplot x=ageatstart y=systolic / name="a2" markerattrs=GraphData1;
    seriesplot x=ageatstart y=diastolic / name="b1" lineattrs=GraphData2;
    scatterplot x=ageatstart y=diastolic / name="b2" markerattrs=GraphData2;
    seriesplot x=ageatstart y=weight / name="c1" lineattrs=GraphData3;
    scatterplot x=ageatstart y=weight / name="c2" markerattrs=GraphData3;
    layout gridded / columns=3 border=true location=outside;
        mergedlegend "a1" "a2" / border=false;
        mergedlegend "b1" "b2" / border=false;
        mergedlegend "c1" "c2" / border=false;
    endlayout;
    endlayout;
    endgraph;
    end;
run;

proc sgrender data=sashelp.heart(obs = 5) template=merged; run;

SGRender.png

View solution in original post

7 REPLIES 7
DanH_sas
SAS Super FREQ

Try this:

  •  Assuming you're using a LAYOUT OVERLAY, create a LAYOUTGRIDDED inside that layout, with BORDER=true, COLUMNS=3, and LOCATION=OUTSIDE.
  • Put three MERGEDLEGENDs in the LAYOUT GRIDDED, one for each of the plots, with BORDER=false

Let me know if this works for you. Thanks!

data_null__
Jade | Level 19

Hi Dan,

Thanks, code below.  These statements are producing this legend.

Capture.PNG

I want total 4 entries, and I thought ADDITIONALNAMES would "merge" the pairs.

   %macro m_plate2(pk=0,ticklist=,cmvar=CMDECOD);
      %let ticklist=%unquote(&ticklist);
      proc template;
          define statgraph cardiac_overlay;
              begingraph;
                  layout lattice / rows=1 rowweights=(1 ); /* 70% for cardiac, 30% for CONMED */

                     layout overlay /
                             yaxisopts = (
                             %if &pk %then %do;
                                 label="PK (ng/mL) & NT-proBNP (pmol/L)"
                                 %end;
                             %else %do;
                                 label="NT-proBNP (pmol/L)"
                                 %end;
                                 labelattrs=(color=red size=9pt)  tickvalueattrs=(color=red size=10pt) offsetmin=.01
                                 )
                             y2axisopts=(label="LVEF (%) & LVOT-G Valsalva (mmHg), (Core Lab)"
                                          offsetmin=.01
                                          labelattrs=(color=blue size=9pt) tickvalueattrs=(color=blue size=10pt)   /*linearopts=(viewmin=40 viewmax=70)*/)
                             xaxisopts=(display=(ticks tickvalues label) label="Week" LABELPOSITION=RIGHT offsetmin=.01 linearopts=(tickvaluelist=(&ticklist) tickvaluefitpolicy=stagger) tickvalueattrs=(size=6pt))
                             ;

                  %if &pk %then %do;
                     seriesplot  x=xval y=PK       /  name='PK' lineattrs=(color=red pattern=solid) yaxis=y /*curvelabel='PK' curvelabelattrs=(color=red size=6pt)*/                  legendlabel='PK (ng/mL)';
                     scatterplot x=xval y=PK       /  name='PK1'          markerattrs=(color=red symbol=circlefilled) yaxis=y datalabel=PK datalabelattrs=(size=6pt)                  legendlabel='PK (ng/mL)';
                     %end;

                     seriesplot x=xval  y=BNPPRONT  / name="BNPPRONT" lineattrs=(color=red pattern=dash) yaxis=y /*curvelabel='NTproBNP' curvelabelattrs=(color=red size=6pt)*/       legendlabel='NT-proBNP (pmol/L)';
                     scatterplot x=xval y=BNPPRONT  / name="BNPPRONT1" markerattrs=(color=red symbol=circle) yaxis=y datalabel=BNPPRONT datalabelattrs=(size=6pt)                     legendlabel='NT-proBNP (pmol/L)';

                     seriesplot  x=xval y=CLVEF     / name="CLVEF"    lineattrs=(color=blue pattern=dash) yaxis=y2  /*curvelabel='LVEF' curvelabelattrs=(color=blue size=6pt)*/       legendlabel='LVEF(%) (Core)';
                     scatterplot x=xval y=CLVEF     / name="CLVEF1"                markerattrs=(color=blue symbol=diamondfilled) yaxis=y2  datalabel=CLVEF datalabelattrs=(size=6pt)  legendlabel='LVEF(%) (Core)';

                     seriesplot  x=xval y=CPGPRESV  / name="CPGPRESV" lineattrs=(color=blue pattern=dash) yaxis=y2  /*curvelabel='LVOTG' curvelabelattrs=(color=blue size=6pt)*/      legendlabel='LVOT-G Valsalva (mmHg) (Core)' ;
                     scatterplot x=xval y=CPGPRESV  / name="CPGPRESV1"                markerattrs=(color=blue symbol=diamond)  yaxis=y2 datalabel=CPGPRESV datalabelattrs=(size=6pt)  legendlabel='LVOT-G Valsalva (mmHg) (Core)' ;
                     innermargin / align=bottom opaque=true backgroundcolor=cxf5f5f5;
                        axistable x=dosdy value=dose / ;
                        axistable x=ady   value=aval / ;
                        endinnermargin;

                      %if &pk %then %do;
                        mergedlegend "PK" 'PK1' /  ADDITIONALNAMES=("BNPPRONT" "BNPPRONT1" "CLVEF" "CLVEF1" 'CPGPRESV' 'CPGPRESV1')  title=' ';
                        %end;
                      %else %do;
                         mergedlegend "BNPPRONT" "BNPPRONT1" / ADDITIONALNAMES=("CLVEF" "CLVEF1" 'CPGPRESV''CPGPRESV1')  title=' ';
                         %end;
                     endlayout;

                  %if 0 %then %do;
                     /* ---- CONMED Data Panel ---- */
                     layout overlay /  xaxisopts=(display=NONE offsetmin=.01 linearopts=(tickvaluelist=(&ticklist) tickvaluefitpolicy=stagger))
                                       yaxisopts=(display=(ticks tickvalues)
                                          /*DISCRETEOPTS=(TICKVALUEFITPOLICY=SPLITALWAYS) */
                                          DISCRETEOPTS=(TICKVALUEFITPOLICY=SPLIT TICKVALUESPLITCHAR=';' sortorder=data )
                                          type=discrete reverse=true tickvalueattrs=(color=black size=5pt))
                                      ;
                         /* HiLo Plot for CONMED */
                         highlowplot Y=&cmvar /*CMDECOD*/ low=s high=e / name="Conmeds"  type=line
                                   lineattrs=(pattern=solid thickness=2) /*markerattrs=(symbol=circlefilled)*/;
                         /* Handling Ongoing Medications */
                         scatterplot x=o y=&cmvar / markerattrs=(symbol=TriangleRightFilled color=red size=6);
                         scatterplot x=p y=&cmvar / markerattrs=(symbol=TriangleLeftFilled color=red size=6);
                     endlayout;
                  %end;
                  endlayout;
              endgraph;
          end;
      run;
      %mend m_plate2;
DanH_sas
SAS Super FREQ

No, ADDTIONALNAMES just adds more "single" items to the merged items. The technique I described (multiple merged legends in the layout gridded) should work for you. Give it a try and let me know.

DanH_sas
SAS Super FREQ

Here is a simple example of what I was describing:

 

proc template;
    define statgraph merged;
    begingraph;
    layout overlay;
    seriesplot x=ageatstart y=systolic / name="a1" lineattrs=GraphData1;
    scatterplot x=ageatstart y=systolic / name="a2" markerattrs=GraphData1;
    seriesplot x=ageatstart y=diastolic / name="b1" lineattrs=GraphData2;
    scatterplot x=ageatstart y=diastolic / name="b2" markerattrs=GraphData2;
    seriesplot x=ageatstart y=weight / name="c1" lineattrs=GraphData3;
    scatterplot x=ageatstart y=weight / name="c2" markerattrs=GraphData3;
    layout gridded / columns=3 border=true location=outside;
        mergedlegend "a1" "a2" / border=false;
        mergedlegend "b1" "b2" / border=false;
        mergedlegend "c1" "c2" / border=false;
    endlayout;
    endlayout;
    endgraph;
    end;
run;

proc sgrender data=sashelp.heart(obs = 5) template=merged; run;

SGRender.png

data_null__
Jade | Level 19

Thanks, this example is very helpful.

DanH_sas
SAS Super FREQ

Looking are your original code gain, I do not think you need to have separate SERIESPLOT and SCATTERPLOT statements. You can display the markers on the SERIESPLOT statement and control the marker attributes. Then, you can use one DISCRETELEGEND for all of your SERIESPLOT statements. For example,

 

seriesplot  x=xval y=PK    /  name='PK' lineattrs=(color=red pattern=solid) yaxis=y legendlabel='PK (ng/mL)'  display=(markers) markerattrs=(color=red symbol=circlefilled) yaxis=y datalabel=PK datalabelattrs=(size=6pt);

 

Ksharp
Super User

John.King ,

Another way is using LEGENDITEM to customize it .

 

/* Step 1: Create Dummy Dataset */
data dummy_data;
    input Subjid $ Age_Group $ Treatment $ AVAL;
    
    /* Numeric representation for Treatment */
    if Treatment = 'DrugA' then trtn = 1;
    else if Treatment = 'DrugB' then trtn = 2;
    else if Treatment = 'Refer' then trtn = 3;

    /* Numeric representation for Age_Group */
    if Age_Group = '5-13' then agegrpn = 1;
    else if Age_Group = '14-21' then agegrpn = 2;
    else if Age_Group = '22-35' then agegrpn = 3;

    datalines;
S01 5-13 DrugA 6000
S02 5-13 DrugA 7000
S03 5-13 DrugB 8000
S04 5-13 DrugB 9000
S05 5-13 Refer 500
S06 5-13 Refer 12000
S07 5-13 DrugA 10000
S08 5-13 DrugB 11000
S09 5-13 Refer 400
S10 14-21 DrugA 4000
S11 14-21 DrugA 5000
S12 14-21 DrugB 6000
S13 5-13 DrugB 7000
S14 14-21 Refer 1000
S15 14-21 Refer 300
S16 22-35 DrugA 8000
S17 14-21 DrugB 9000
S18 14-21 Refer 100
S19 22-35 DrugA 200
S20 22-35 DrugA 300
S21 22-35 DrugB 400
S22 22-35 DrugB 500
S23 22-35 Refer 50
S24 14-21 Refer 100
S25 22-35 DrugA 600
S26 22-35 DrugB 700
S27 22-35 Refer 150
S28 5-13 DrugA 8000
;
run;


proc sort data=dummy_data; 
by trtn agegrpn; 
run;

proc means data=dummy_data nway noprint;
/*	by trtn strat2rn;*/
/*	var pchg;*/
by trtn agegrpn; 
	var aval;
	*output out=statall min= max= median= mean= n= q1 = q3 =/autoname;
	output out=stat n=n mean=mean median=median;
run;
data final;
	merge dummy_data stat(drop=_:);
	by trtn agegrpn; 
	num =1;
if TREATMENT='DrugA' then do;mean1=mean;median1=median;end;
if TREATMENT='DrugB' then do;mean2=mean;median2=median;end;
if TREATMENT='Refer' then do;mean3=mean;median3=median;end;

run;


proc template;
    define statgraph boxplot;

    begingraph / datacolors=(lightblue lightgreen  lightgrey) datacontrastcolors=(lightblue lightgreen  lightgrey) 
datasymbols=(trianglefilled squarefilled circlefilled);

        /* Define Custom Attributes for Age Groups */
        discreteattrmap name="groupline" / ignorecase=true;
            value 'DrugA' / lineattrs=(color=lightblue pattern=1 thickness=2px)
                markerattrs=(color=lightblue symbol=trianglefilled size=8pt)
                textattrs=(color=lightblue);
            value 'DrugB' / lineattrs=(color=lightgreen pattern=1 thickness=2px)
                markerattrs=(color=green symbol=squarefilled size=8pt)
                textattrs=(color=lightgreen);
            value 'Refer' / lineattrs=(color=grey pattern=1 thickness=2px)
                markerattrs=(color=grey symbol=circlefilled size=8pt)
                textattrs=(color=grey);
        enddiscreteattrmap;

        discreteattrvar attrvar=trtgrp var=trtn attrmap='groupline';

        /* Add Custom Legends */
        legenditem type=markerline name='A' / lineattrs=(color=blue pattern=1 thickness=2px)
            markerattrs=(color=blue size=8pt symbol=trianglefilled)
            label="DrugA" labelattrs=(size=9pt);
        legenditem type=markerline name='B' / lineattrs=(color=green pattern=1 thickness=2px)
            markerattrs=(color=green size=8pt symbol=squarefilled)
            label="DrugB" labelattrs=(size=9pt);
        legenditem type=markerline name='R' / lineattrs=(color=grey pattern=1 thickness=2px)
            markerattrs=(color=grey size=8pt symbol=circlefilled)
            label="Refer" labelattrs=(size=9pt);

        layout overlay / 
            xaxisopts=(offsetmin=0.12 offsetmax=0.12 label="Age Groups" labelattrs=(size=12pt weight=bold) 
                tickvalueattrs=(size=12pt weight=bold))
            yaxisopts=(offsetmin=0.05 offsetmax=0.05 label="Results" labelfitpolicy=splitalways labelsplitchar='^' 
                labelattrs=(size=11pt weight=bold) tickvalueattrs=(size=12pt weight=bold) 
                linearopts=(tickvaluesequence=(start=-2000 end=15000 increment=1000) viewmin=-2000 viewmax=15000));

        /* Reference Line */
        referenceline y=0 / lineattrs=(color=grey pattern=3);

        /* Box Plot */
        boxplot x=agegrpn y=AVAL / group=trtn groupdisplay=cluster boxwidth=0.56 clusterwidth=0.53  ;

        /*scatter of mean*/
	   scatterplot x=agegrpn y=mean1/group=treatment groupdisplay=cluster clusterwidth=0.53  markerattrs=(symbol=trianglefilled color=blue);
	   scatterplot x=agegrpn y=mean2/group=treatment groupdisplay=cluster clusterwidth=0.53  markerattrs=(symbol=squarefilled color=green);
	   scatterplot x=agegrpn y=mean3/group=treatment groupdisplay=cluster clusterwidth=0.53  markerattrs=(symbol=circlefilled color=grey);

        /*scatter of median*/
	   highlowplot x=agegrpn low=median1 high=median1/group=treatment groupdisplay=cluster clusterwidth=0.53 type=bar barwidth=0.6 outlineattrs=(thickness=2px color=blue) ;
	   highlowplot x=agegrpn low=median2 high=median2/group=treatment groupdisplay=cluster clusterwidth=0.53 type=bar barwidth=0.6 outlineattrs=(thickness=2px color=green) ;
	   highlowplot x=agegrpn low=median3 high=median3/group=treatment groupdisplay=cluster clusterwidth=0.53 type=bar barwidth=0.6 outlineattrs=(thickness=2px color=grey) ;

        /* Legend */
        discretelegend 'A' 'B' 'R' / down=1 border=false;

        /* Axis Table */
        innermargin;
            axistable x=agegrpn value=num / class=trtn  classdisplay=cluster clusterwidth=0.53 classorder=ascending 
                valueattrs=(weight=bold) labelattrs=(weight=bold) colorgroup=trtgrp ; 
        endinnermargin;

        endlayout;
    endgraph;
end;
run;
proc format;
   value agegrpn
      1="5-13"
      2="14-21"
      3="22-35"
			;
	value treatment 
		1="DrugA"
		2="DrugB"
		3="Refer"
			;
run;

ods graphics/reset=all;
proc sgrender data=final template=boxplot;
    format trtn treatment. agegrpn agegrpn.;
run;

Ksharp_0-1738637706176.png

 

 

P.S.

You need to make a GROUP variable to make it happen if you want to use MERGEDLEGEND.

/***********************/
proc sort data=sashelp.class
out =class;
by sex;
run;
proc template;
define statgraph mergedLegend;
begingraph;
entrytitle "Linear Regression By Gender";
layout overlay;
scatterplot x=height y=weight / group=sex name="scat";
regressionplot x=height y=weight/ group=sex name="reg";
mergedlegend "scat" "reg" / border=true;
endlayout;
endgraph;
end;
proc sgrender data=class template=mergedLegend;
run;

Ksharp_0-1738638266183.png

 

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 1625 views
  • 7 likes
  • 3 in conversation