Clinical Graphs using SAS 9.3

Clinical Graphs using SAS® 9.3
Sanjay Matange, SAS Institute Inc.
SAS Global Forum 2015
In their 2008 paper “Graphical Approaches to the
Analysis of Safety Data from Clinical Trials”, Ohad
Amit, et al. have provided valuable insight into and
recommendations for the analysis of safety data.
The authors see several opportunities to enhance
the evaluation of safety through use of graphical
display of data including Dot Plots, Box Plots,
Lattice and Matrix Displays. Graphical display of
data provides insights into trends and correlations
that are just not visible in the tabular data. Often,
combining the data and summary statistics on a
single display helps improve the analysis and
interpretation of the results.
In this handout, we show how you can use the SAS
9.3 SG Procedures and GTL to create clinical
graphs by using features such as cluster groups,
grouped box plots on discrete and interval axis and
attribute maps.
Annotation is supported with the
SG Procedures, making it easier to create these
graphs.
A GTL program may be required to create some of
the multi-cell graphs. The data for the graphs
shown here is simulated. Some graphs included in
this handout have been contributed by Susan
Schwartz and Melisa Turner.
The examples shown here include display of Lab
Result over Time, Distribution of lab values by Test
and Treatment, Lattice and Matrix displays of LFT
tests, Patient Profiles, Adverse Event Plots sorted
by relative risk and Hazard Function Plots.
The code shown below each graph is reduced to fit the available space. The intention is to show the
structure and key statements.
The complete programs for these graphs are available at
http://support.sas.com/rnd/datavisualization/yourGraphs/analyticalCustom/clinical.
title 'LFT Safety Panel, Baseline vs. Study';
footnote2 j=l italic height=8pt "* For ALAT, ASAT …”;
footnote3 j=l italic height=8pt " For Bilirubin Total, …”;
proc sgpanel data=labs;
panelby labtest visitnum / layout=lattice onepanel novarname;
scatter x=pre y=result/ group=drug markerattrs=(size=9);
refline 1 1.5 2 / axis=Y lineattrs=(pattern=dash);
refline 1 1.5 2 / axis=X lineattrs=(pattern=dash);
rowaxis integer min=0 max=4 label='Study (/ULN)' ;
colaxis integer min=0 max=4 label='Baseline (/ULN) *';
keylegend/title=" " noborder;
run;
begingraph / <options>;
entrytitle "Lab Values by Study Week";
layout gridded / rowgutter=5;
layout datapanel classvars=(treatment) / <options>;
layout prototype / cycleattrs=true;
seriesplot X=visit Y=sgot / <options>;
seriesplot X=visit Y=aph / yaxis=Y2 <options>;
endlayout;
endlayout;
discretelegend "series1" "series2" / <options> ;
endlayout;
endgraph;
begingraph / <options>;
entrytitle 'Distribution of Maximum Liver Function Test …’;
layout overlay / < yaxisopts > <y2axisopts> <xaxisopts>;
boxplot x=Test y=A / discreteoffset=-0.2 boxwidth=.2
name='a' legendlabel='Drug A (N=209)' <options>;
boxplot x=Test y=B / discreteoffset=0.2 boxwidth=.2
name='b' legendlabel='Drug B (N=405)' yaxis=y2 <options>;
referenceline y=1 / lineattrs=(pattern=dot);
dropline x='BILTOT' y=1.5 / dropto=Y yaxis=y2
discreteoffset=-.4 <options>;
dropline x='ALKPH' y=2.0 / dropto=Y yaxis=y
discreteoffset=.4 <options>;
discretelegend 'a' 'b' / location=inside <options>;
endlayout;
endgraph;
begingraph / <options>;
entrytitle 'Hazard Function for Adverse Events …';
layout overlay / yaxisopts=(label='Hazard Rate') <options>;
stepplot x=day y=A / errorupper=AHigh errorlower=ALow
justify=center name='a' <options>;
stepplot x=day y=B / errorupper=BHigh errorlower=BLow
justify=center name='b' < options>;
discretelegend 'a' 'b' / location=inside across=1 <options>;
innermargin;
blockplot x=day block=BRisk / <options>;
blockplot x=day block=ARisk / <options>;
endinnermargin;
endlayout;
entryfootnote halign=left 'Table: Average number of …”;
endgraph;
title 'Median of Lipid Profile by Visit and Treatment';
proc sgplot data=lipid_grp;
scatter x=day y=median / yerrorlower=lcl yerrorupper=ucl
group=trt groupdisplay=cluster clusterwidth=0.5
markerattrs=(symbol=circlefilled);
series x=day y=median / group=trt groupdisplay=cluster
clusterwidth=0.5 lineattrs=(thickness=2) name='s';
yaxis label='Median with 95% CL' grid;
xaxis display=(nolabel);
keylegend 's' / title='Treatment' location=inside
position=topright across=1;
run;
title "Adverse Events for Patient Id = xx-xxx-xxxx";
proc sgplot data=ae2 nocycleattrs dattrmap=attrmap;
highlow y=aeseq low=stday high=enday / group=aesev
lowlabel=aedecod type=bar
barwidth=0.8 lineattrs=(color=black) lowcap=lcap highcap=hcap
attrid=Severity name='sev';
scatter x=aestdate y=aeseq / markerattrs=(size=0) x2axis;
refline 0 / axis=x lineattrs=(thickness=1 color=black);
yaxis display=(nolabel noticks novalues) type=discrete;
xaxis grid label='Study' values=(&minda to &maxday by 2);
x2axis notimesplit values=(&mindate to &maxdate);
keylegend 'sev'/ title='Severity :';
run;
begingraph;
entrytitle 'Distribution of ASAT by Time and Treatment';
layout lattice / columns=1 COLUMNDATARANGE=UNION
columndatarange=union rowweights=(0.07 0.86 0.07);
columnaxes;
columnaxis / display=(tickvalues)
linearopts=(tickvaluelist=(0 1 2 4 8 12 24 26));
endcolumnaxes;
layout overlay / yaxisopts=(display=(tickvalues));
scatterplot x=week y=over2label / group=Drug
markercharacter=over2 ;
referenceline x=25 / lineattrs=(pattern=solid);
endlayout;
layout overlay / xaxisopts = (display=(tickvalues label));
boxplot x=week y=value / group=drug name="d"
whiskerattrs=(thickness=2) groupdisplay=cluster
display=(mean median outliers) outlineattrs=(thickness=2);
referenceline x=25 / lineattrs=(pattern=solid);
referenceline y=1.0 / lineattrs=(pattern=shortdash);
referenceline y=2.0 / lineattrs=(pattern=dash);
referenceline y=0 / lineattrs=(pattern=dash);
endlayout;
layout overlay / xaxisopts=(display=none)
yaxisopts=(display=(tickvalues));
scatterplot x=week y=drug / group=Drug clusterwidth=0.5
markercharacter=atrisk;
referenceline x=25 / lineattrs=(pattern=solid);
endlayout;
sidebar / align=bottom spacefill=false;
discretelegend "Drug A" "Drug B";
endsidebar;
endLayout;
endgraph;
end;
run;
begingraph / <options>;
entrytitle 'Matrix Display of Maximum LFT Values';
layout lattice / columns=3 columndatarange=union
rowdatarange=union order=rowmajor <options>;
sidebar;
layout overlay;
discretelegend 's' / across=2 border=false;
endlayout;
endsidebar;
/* Column Axes Block */
/* Row Axes Block */
layout overlay / yaxisopts=(linearopts=(thresholdmax=1));
scatterplot x=asat y=alat / group=drug name='s' <options>;
/* Reference lines */
endlayout;
/* Empty Cell */
/* Empty Cell */
layout overlay / yaxisopts=(linearopts=(thresholdmax=1));
scatterplot x=asat y=biltot / group=drug <options>;
/* Reference lines */
endlayout;
layout overlay / yaxisopts=(linearopts=(thresholdmax=1));
scatterplot x=alat y=biltot / group=drug <options>;
/* Reference lines */
endlayout;
/* Empty Cell */
layout overlay / yaxisopts=(linearopts=(thresholdmax=1));
scatterplot x=asat y=alkph / group=drug <options>;
/* Reference lines */
endlayout;
layout overlay / yaxisopts=(linearopts=(thresholdmax=1));
scatterplot x=alat y=alkph / group=drug <options>;
/* Reference lines */
endlayout;
layout overlay / yaxisopts=(linearopts=(thresholdmax=1));
scatterplot x=biltot y=alkph / group=drug <options>;
/* Reference lines */
endlayout;
endlayout;
entryfootnote halign=left "For ALAT, ASAT …”;
entryfootnote halign=left "For BILTOT, the …";
endgraph;
begingraph / <options>;
entrytitle 'Immunology Profile by Treatment';
layout gridded;
layout datalattice columnvar=trt rowvar=lbparm / <options>;
layout prototype;
blockplot x=xval block=cyc / <options>;
seriesplot x=xval y=sival / group=pt name='a' <options>;
endlayout;
endlayout;
discretelegend 'a' / title ='Patient' across=8;
endlayout;
endgraph;
title 'Depression After Treatment by Visit and Treatment';
proc sgpanel data=depression;
panelby phase / layout=columnlattice onepanel novarname
uniscale=row spacing=2;
vbox score / category=visit group=trt clusterwidth=0.75
boxwidth=0.9 transparency=0.3
lineattrs=(color=black) whiskerattrs=(color=black);
colaxis display=(nolabel);
rowaxis grid;
run;
proc sgplot data=eyeIrritation;
vbarparm category=time response=percent / group=chartvar
limitupper=ucl limitlower=lcl dataskin=gloss transparency=0.3
barwidth=0.9 limitattrs=graphdatadefault;
scatter x=time y=yn / group=chartvar groupdisplay=cluster
y2axis markerchar=n markercharattrs=graphdatadefault;
yaxis offsetmin=0.05 grid max=100;
y2axis offsetmax=0.97 display=none;
xaxis display=(nolabel);
run;
title 'Top Twenty Adverse Events Sorted by Frequency';
proc sgplot data=aerev;
refline refline / lineattrs=graphdata1(thickness=16)
transparency=0.8;
scatter y=aedecod x=percent / group=arm name='scatter';
keylegend / location=inside position=bottomright across=1;
xaxis display=(nolabel) ;
yaxis display=(nolabel) offsetmin=0.03 offsetmax=0.03;
run;
For more examples, tips and tricks on creating graphs using SG Procedures and GTL, visit our blog at
http://blogs.sas.com/content/graphicallyspeaking/.