I can't figure out how to align the lower plots in a multi cell layout using a nested layout lattice with two columns with two two plots in the left column and 3 in the right column.
Any ideas?
The code is :
proc template;
define statgraph lab_view;
begingraph ;
discreteattrmap name="treat" / ignorecase=true;
value "Comparator" / markerattrs=GraphData1 (color=&col_comparator. symbol=&symb_comparator.) lineattrs=GraphData1 ( color=&col_comparator. pattern=&pat_comparator.);
value "Dula 0.75 mg" / markerattrs=GraphData1 (color=&col_dula_075_mg. symbol=&symb_dula_075_mg.) lineattrs=GraphData1 ( color=&col_dula_075_mg. pattern=&pat_dula_075_mg.);
value "Empa 25 mg" / markerattrs=GraphData1 (color=&col_empa_25_mg. symbol=&symb_empa_25_mg.) lineattrs=GraphData1 ( color=&col_empa_25_mg. pattern=&pat_empa_25_mg.);
value "Lira 0.9 mg" / markerattrs=GraphData1 (color=&col_lira_09_mg. symbol=&symb_lira_09_mg.) lineattrs=GraphData1 ( color=&col_lira_09_mg. pattern=&pat_lira_09_mg.);
value "Lira 1.8 mg" / markerattrs=GraphData1 (color=&col_lira_18_mg. symbol=&symb_lira_18_mg.) lineattrs=GraphData1 ( color=&col_lira_18_mg. pattern=&pat_lira_18_mg.);
value "Oral sema" / markerattrs=GraphData1 (color=&col_oral_sema. symbol=&symb_oral_sema.) lineattrs=GraphData1 ( color=&col_oral_sema. pattern=&pat_oral_sema.);
value "Oral sema 7 mg" / markerattrs=GraphData1 (color=&col_oral_sema_7_mg. symbol=&symb_oral_sema_7_mg.) lineattrs=GraphData1 ( color=&col_oral_sema_7_mg. pattern=&pat_oral_sema_7_mg.);
value "Oral sema 14 mg" / markerattrs=GraphData1 (color=&col_oral_sema_14_mg. symbol=&symb_oral_sema_14_mg.) lineattrs=GraphData1 ( color=&col_oral_sema_14_mg. pattern=&pat_oral_sema_14_mg.);
value "Oral sema flex" / markerattrs=GraphData1 (color=&col_oral_sema_flex. symbol=&symb_oral_sema_flex.) lineattrs=GraphData1 ( color=&col_oral_sema_flex. pattern=&pat_oral_sema_flex.);
value "Placebo" / markerattrs=GraphData1 (color=&col_placebo. symbol=&symb_placebo.) lineattrs=GraphData1 ( color=&col_placebo. pattern=&pat_placebo.);
value "Sita 100 mg" / markerattrs=GraphData1 (color=&col_sita_100_mg. symbol=&symb_sita_100_mg.) lineattrs=GraphData1 ( color=&col_sita_100_mg. pattern=&pat_sita_100_mg.);
enddiscreteattrmap;
discreteattrvar attrvar=treatmentmarkers var=&treatVar. attrmap="treat";
layout lattice / columns=2 ;
/* first col*/
layout lattice /columndatarange=union
rowdatarange=unionall;
columnaxes;
columnaxis / display= standard
label=" "
linearopts=(tickvaluelist=(&VISITS..));
endcolumnaxes;
layout overlay /yaxisopts=(display =(ticks tickvalues))
xaxisopts=(display =(ticks tickvalues));
scatterplot x=AVISIT2N y=aval / group=treatmentmarkers
groupdisplay=cluster
clusterwidth=0.7
jitter=auto;
endlayout;
layout overlay/yaxisopts=(display =(ticks tickvalues))
xaxisopts=(display =(ticks tickvalues));
highlowplot x=AVISIT2N high=P95 low=P5 / group=treatmentmarkers groupdisplay=cluster clusterwidth=0.7 highcap=serif lowcap=serif;
highlowplot x=AVISIT2N high=q3 low=median / group=treatmentmarkers type=bar fillattrs=(color=white) groupdisplay=cluster clusterwidth=0.7 barwidth=0.7;
highlowplot x=AVISIT2N high=median low=q1 / group=treatmentmarkers type=bar fillattrs=(color=white) groupdisplay=cluster clusterwidth=0.7 barwidth=0.7;
scatterplot x=AVISIT2N y=mean / group=treatmentmarkers groupdisplay=cluster clusterwidth=0.7 name='treat';
seriesplot x=AVISIT2N y=mean / group=treatmentmarkers groupdisplay=cluster name='curve';
endlayout;
endlayout;
/*second col*/
layout lattice / columndatarange=union
/* rowdatarange=unionall*/
rowweights = (0.45 0.45 0.10);
columnaxes;
columnaxis / display= standard
label=" "
linearopts=(tickvaluelist=(&VISITS..));
;
endcolumnaxes;
/* spagetti plots*/
layout overlay /y2axisopts=(display =(ticks tickvalues)) ;
seriesplot x=AVISIT2N y=_1 /group=usubjid
yaxis=y2
lineattrs=(color=&col_treat_1. pattern=&pat_treat_1.);
endlayout;
layout overlay /y2axisopts=(display =(ticks tickvalues));
seriesplot x=AVISIT2N y=_2 /group=usubjid
yaxis=y2
lineattrs=(color=&col_treat_2. pattern=&pat_treat_2.);
endlayout;
/* number of subjects*/
layout overlay / xaxisopts=(display =(ticks tickvalues))
y2axisopts=(display =(ticks tickvalues)
reverse=true
tickvalueattrs=(size= 6));
scatterplot x = AVISIT2N y = &treatVar. / markercharacter = count
markercharacterATTRS=(color=black )
yaxis=y2;
endlayout;
endlayout;
endlayout;
endgraph;
end;
run;
proc sgrender data=data_for_plot template=lab_view;
Actually, now that you have a true 2x2 lattice, you should remove the "interior" lattice layouts and just add the plot to the one outer LATTICE layout with columns=2 and no weighting.
Can you better describe how you want them aligned? Are you just concerned with the outer edges, or are you looking for some kind of internal alignment?
It its the two x axis from each column at the bottom - see marked in yellow below
What version or SAS are you using?
Instead of using three cells with a SCATTERPLOT, try using two cells with an AXISTABLE. Your code for the second lattice will look something like the following (untested):
layout lattice / columndatarange=union
/* rowdatarange=unionall*/
rowweights = (0.45 0.55);
columnaxes;
columnaxis / display= standard
label=" "
linearopts=(tickvaluelist=(&VISITS..));
;
endcolumnaxes;
/* spagetti plots*/
layout overlay /y2axisopts=(display =(ticks tickvalues)) ;
seriesplot x=AVISIT2N y=_1 /group=usubjid
yaxis=y2
lineattrs=(color=&col_treat_1. pattern=&pat_treat_1.);
endlayout;
layout overlay /y2axisopts=(display =(ticks tickvalues));
seriesplot x=AVISIT2N y=_2 /group=usubjid
yaxis=y2
lineattrs=(color=&col_treat_2. pattern=&pat_treat_2.);
innermargin;
axistable x = AVISIT2N value=count / class=&treatVar valueattrs=(color=black ) yaxis=y2;
endinnermargin;
endlayout;
endlayout;
Thanks for the tips on the axistable. Still not 100% aligned at the bottom but acceptable.
A few more questions:
How do I get the display for axistable to show on the right side (shown with arrows below)
Is it possible to get one common xaxis label for the two columns and for the rows as well ?
/*second col*/
layout lattice / columndatarange=union
rowweights = (0.48 0.52);
columnaxes;
columnaxis / display=all
label="&xlabel."
linearopts=(tickvaluelist=(&VISITS.));
endcolumnaxes;
rowaxes;
rowaxis /display=all label=%str("&ylabel.");
endrowaxes;
/* spagetti plots*/
layout overlay /y2axisopts=(display =(ticks tickvalues label)
label=%str("&ylabel.")
linearopts=(viewmin=&ymin. viewmax=&ymax.));
seriesplot x=AVISIT2N y=_1 /group=usubjid
yaxis=y2
lineattrs=(color=&col_treat_1. pattern=&pat_treat_1.);
endlayout;
layout overlay /y2axisopts=(display =(ticks tickvalues label)
label=%str("&ylabel.")
linearopts=(viewmin=&ymin. viewmax=&ymax.));
seriesplot x=AVISIT2N y=_2 /group=usubjid
yaxis=y2
lineattrs=(color=&col_treat_2. pattern=&pat_treat_2.);
/*table with number of subjects*/
innermargin;
axistable x=AVISIT2N value=count / class=&treatVar. valueattrs=(color=black) yaxis=y2 labelattrs=(size=6);
endinnermargin;
referenceline y=&ymin. /yaxis=y2;
endlayout;
endlayout;
endlayout;
endgraph;
end;
run;
Add LABELPOSITION=MAX to the AXISTABLE statement.
Actually, now that you have a true 2x2 lattice, you should remove the "interior" lattice layouts and just add the plot to the one outer LATTICE layout with columns=2 and no weighting.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.