Return to Safety Graphics Home

Table of Contents

Type of Graph: Line Plot

Last updated by Main.FabriceBancken on August 26, 2011

Type of Data: Categorical and Continuous

Description and purpose:

The line plot displays either summary data (e.g., mean and 95 CI limits)or a subject's individual measurements (otherwise known as subject's profile) summary data at a series of time points.

In both cases, the X axis typically represents time, and therefore must be a quantitative axis, in the sense that the distance on the graph between 2 time points should be proportional to the time difference between those timepoints

For summary data,, the Y axis represents the summary results at the time point under consideration which - in most cases - are represented by a symbol and (vertical) error bar.

For subject's profiles, a symbol located at (x,y) represents the result y(laboratory result, vital signs, etc) for the subject under consideration at the time point x. (Example 4)

Connecting lines: The symbols representing points estimates may be connected with lines to outline trends over time.

Special features:

Margin : A margin can be drawn in the plot to hold a particular result. For example, when depicting the change from baseline at each time point during a study [based on available data at the timepoint], one may want to have a margin or side panel in which sensitivity analysis results are shown (LOCF, or other estimate obtained with more sophisticated techniques accounting for missing data). (see Example 1)

A good practice also to display the number of subjects who contributed to the summary data at timepoint Xi (i=1, ...n) (see Example 1). This can be displayed using text or using a bottom small side panel holding another lien plott (see Example 2)


%LIGHTBOX{ image="Bancken_LinePlotExample1.png" thumbnail="Bancken_LinePlotExample1_200.png" }%

Example 1:

Click on image to enlarge.

Click for Code Example1

Code (Example 1 ):

%CODE{lang="java"}% %autorun;

proc format; ; value groupf 1 = 'Active' 2 = 'Control' ; value grpsf 1 = 'Act' 2 = 'Ctr' ; value ep 1="Endpoint"; run;

data smrydata; set data_a.figure8_data; if treat="Active" then grp=1;else grp=2; grp2=grp; if week=16 then do; timeq=.; timeq2=1+(grp-1.5)*0.20; end; else do; timeq=week+(grp-1.5)*0.20; *bring a slight horizontal shift to avoid error bars to overlap; timeq2=.; *timeq - to use in the left column panels, timeq2 to use in the right col panels; end; run;

proc print;

title; proc template; define style styles.redblue; parent = styles.default; class GraphColors "Abstract colors used in graph styles" / 'gcdata1' = cx0300B3 'gcdata2' = cxFD1808; style color_list from color_list "Abstract colors used in graph styles" / 'bgA' = cxffffff; end; run;

* version with lines ;

proc template; define statgraph GroupedLG; begingraph; entrytitle 'Mean Change from Baseline in ALT (U/L)'; entryfootnote halign=left 'n.obs = Number of Observations at Time point in Treatment group'; layout lattice / columns=2 columngutter=0 columnweights=(.80 .20) rows=2 rowweights=(.70 .30); *left upper cell with results over time; sidebar / align=top; discretelegend "a" / title="Treatment Group"; endsidebar; layout overlay / xaxisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) x2axisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) yaxisopts=(label="Mean (95%%CI) Change from Bsl." griddisplay=on linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.10) viewmin=-0.05 viewmax=0.65)) y2axisopts=(display=(line) linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.10) viewmin=-0.05 viewmax=0.65)); scatterplot x=timeq y=meanchg / group=grp2 name='a' yerrorlower=loerror yerrorupper=uperror ; seriesplot x=timeq y=meanchg / group=grp2; scatterplot x=timeq y=meanchg / markerattrs=(size=0) xaxis=x2 yaxis=y2; endlayout; *right upper cell with results at Endpoint; layout overlay / yaxisopts=(display=(line ticks) griddisplay=on linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.1) viewmin=-0.05 viewmax=0.65)) y2axisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.1) viewmin=-0.05 viewmax=0.65)) xaxisopts=(display=(line) linearopts=(tickvaluelist=(1) viewmin=0 viewmax=2) offsetmin=0 offsetmax=0) x2axisopts=(display=(line)linearopts=(tickvaluelist=(1) viewmin=0 viewmax=2) offsetmin=0 offsetmax=0); scatterplot x=timeq2 y=endpoint / group=grp2 yerrorlower=loerror yerrorupper=uperror; scatterplot x=timeq2 y=endpoint / markerattrs=(size=0) xaxis=x2 yaxis=y2; endlayout; *left lower cell with number of observations over time; layout overlay / xaxisopts=(label="Time (Weeks)" linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) yaxisopts=(label="n.obs." linearopts=(tickvaluelist=(1 2) viewmin=0.5 viewmax=2.5)); scatterplot y=grp x=timeq / group=grp2 markercharacter=atrisk markercharacterattrs=(Size=8pt Family=GraphValueText:FontFamily) ; endlayout; *right lower cell with number of observations at Endpoint; layout overlay / xaxisopts=(display=(line label) label="Endpoint" linearopts=(tickvaluelist=(1) viewmin=0 viewmax=2) offsetmin=0 offsetmax=0) yaxisopts=(display=(line) linearopts=(tickvaluelist=(1 2) viewmin=0.5 viewmax=2.5)); scatterplot y=grp x=timeq2 / group=grp2 markercharacter=atrisk markercharacterattrs=(Size=8pt Family=GraphValueText:FontFamily); endlayout;

endlayout; endgraph; end; run;

ods listing close; ods rtf style=Styles.Redblue file="./lgplot_example01.rtf"; goptions reset=goptions device=sasemf target=sasemf ftext='Arial' ftitle='Arial/bold'; ods graphics / reset noborder width=600px height=450px noscale; proc sgrender data=smrydata template=GroupedLG; format grp grpsf. grp2 groupf. timeq2 ep. ; run; ODS RTF CLOSE; ods listing; quit; ; %ENDCODE%


%LIGHTBOX{ image="Bancken_LinePlotExample2.png" thumbnail="Bancken_LinePlotExample2_200.png" }%

Example 2:

Click on image to enlarge.

Click for Code Example 2

Code (Example 2 ):

%CODE{lang="java"}% %autorun;

proc format; ; value groupf 1 = 'Active' 2 = 'Control' ; value grpsf 1 = 'Act' 2 = 'Ctr' ; value ep 1="Endpoint"; run;

data smrydata; set data_a.figure8_data; if treat="Active" then grp=1;else grp=2; grp2=grp; if week=16 then do; timeq=.; timeq2=1+(grp-1.5)*0.20; end; else do; timeq=week+(grp-1.5)*0.20; *bring a slight horizontal shift to avoid error bars to overlap; timeq2=.; *timeq - to use in the left column panels, timeq2 to use in the right col panels; end; run;

proc print;

title; proc template; define style styles.redblue; parent = styles.default; class GraphColors "Abstract colors used in graph styles" / 'gcdata1' = cx0300B3 'gcdata2' = cxFD1808; style color_list from color_list "Abstract colors used in graph styles" / 'bgA' = cxffffff; end; run;

* version with lines ;

proc template; define statgraph GroupedLG; begingraph; entrytitle 'Mean Change from Baseline in ALT (U/L)'; entryfootnote halign=left 'n.obs = Number of Observations at Time point in Treatment group'; layout lattice / rows=2 rowweights=(.65 .35); *upper cell with results over time; sidebar / align=top; discretelegend "a" / title="Treatment Group"; endsidebar; layout overlay / yaxisopts=(label="Mean (95%%CI) Change from Bsl." griddisplay=on linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.1) viewmin=-0.05 viewmax=0.65)) y2axisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.1) viewmin=-0.05 viewmax=0.65)) xaxisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) x2axisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5));

scatterplot x=timeq y=meanchg / group=grp2 name='a' yerrorlower=loerror yerrorupper=uperror ; seriesplot x=timeq y=meanchg / group=grp2 xaxis=x2 yaxis=y2; endlayout;

*lower cell with number of observations over time; layout overlay / xaxisopts=(label="Time (Weeks)" linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) x2axisopts=(display=(line) linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) yaxisopts=(label="n.obs." griddisplay=on linearopts=(tickvaluesequence=(start=130 end=180 increment=10) viewmin=125 viewmax=185)) y2axisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=130 end=180 increment=10) viewmin=125 viewmax=185));

scatterplot x=timeq y=atrisk / group=grp2 ; seriesplot x=timeq y=atrisk / group=grp2 xaxis=x2 yaxis=y2; endlayout;

endlayout; endgraph; end; run;

ods listing close; ods rtf style=Styles.Redblue file="./lgplot_example03.rtf"; goptions reset=goptions device=sasemf target=sasemf ftext='Arial' ftitle='Arial/bold'; ods graphics / reset noborder width=600px height=600px noscale; proc sgrender data=smrydata template=GroupedLG; format grp grpsf. grp2 groupf. timeq2 ep. ; run; ODS RTF CLOSE; ods listing; quit; ; %ENDCODE%


%LIGHTBOX{ image="Bancken_LinePlotExample2.png" thumbnail="Bancken_LinePlotExample3_200.png" }%

Example 3:

Click on image to enlarge.

Click for Code Example 3

Code (Example 3 ):

%CODE{lang="java"}% %autorun;

proc format; ; value groupf 1 = 'Active' 2 = 'Control' ; value grpsf 1 = 'Act' 2 = 'Ctr' ; value ep 1="Endpoint"; run;

data smrydata; set data_a.figure8_data; if treat="Active" then grp=1;else grp=2; grp2=grp; if week=16 then do; timeq=.; timeq2=1+(grp-1.5)*0.20; end; else do; timeq=week+(grp-1.5)*0.20; *bring a slight horizontal shift to avoid error bars to overlap; timeq2=.; *timeq - to use in the left column panels, timeq2 to use in the right col panels; end; run;

proc print;

title; proc template; define style styles.redblue; parent = styles.default; class GraphColors "Abstract colors used in graph styles" / 'gcdata1' = cx0300B3 'gcdata2' = cxFD1808; style color_list from color_list "Abstract colors used in graph styles" / 'bgA' = cxffffff; end; run;

* version with lines ;

proc template; define statgraph GroupedLG; begingraph; entrytitle 'Mean Change from Baseline in ALT (U/L)'; entryfootnote halign=left 'n.obs = Number of Observations at Time point in Treatment group'; layout lattice / rows=2 rowweights=(.70 .30); *upper cell with results over time; sidebar / align=top; discretelegend "a" / title="Treatment Group"; endsidebar; layout overlay / yaxisopts=(label="Mean (95%%CI) Change from Bsl." griddisplay=on linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.1) viewmin=-0.05 viewmax=0.65)) y2axisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=0.6 increment=0.1) viewmin=-0.05 viewmax=0.65)) xaxisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) x2axisopts=(display=(line ticks) linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)); scatterplot x=timeq y=meanchg / group=grp2 name='a' yerrorlower=loerror yerrorupper=uperror ; seriesplot x=timeq y=meanchg / group=grp2 xaxis=x2 yaxis=y2; endlayout;

*lower cell with number of observations over time; layout overlay / xaxisopts=(label="Time (Weeks)" linearopts=(tickvaluesequence=(start=0 end=12 increment=2) viewmin=-0.5 viewmax=12.5)) yaxisopts=(label="n.obs." linearopts=(tickvaluelist=(1 2) viewmin=0.5 viewmax=2.5)); scatterplot y=grp x=timeq / group=grp2 markercharacter=atrisk markercharacterattrs=(Size=8pt Family=GraphValueText:FontFamily) ; endlayout;

endlayout; endgraph; end; run;

ods listing close; ods rtf style=Styles.Redblue file="./lgplot_example02.rtf"; goptions reset=goptions device=sasemf target=sasemf ftext='Arial' ftitle='Arial/bold'; ods graphics / reset noborder width=600px height=450px noscale; proc sgrender data=smrydata template=GroupedLG; format grp grpsf. grp2 groupf. timeq2 ep. ; run; ODS RTF CLOSE; ods listing; quit; ; %ENDCODE%

Example 4

Figure_6_200.PNG

Click for Code Example 4

Code (Example 4 ):

%CODE{lang="java"}% data labs (keep=patient relday sday alat biltot alkph asat miny); length patient $50; label alat="ALAT"; label biltot="Bilirubin Total"; label alkph="Alk Phos"; label asat="ASAT"; label relday="Day"; label miny="Trial Duration";

patient="Patient 5152: White Male Age 48; Drug: A"; do relday = -25 to 175 by 25; alat = 0.5 + 4 * sin(3.14 * (relday+25) / 360.0); asat = 0.5 + 3 * sin(3.14 * (relday+25) / 400.0); alkph = 0.4 + 2 * sin(3.14 * (relday+25) / 540.0); biltot = 0.4 + 1 * sin(3.14 * (relday+25) / 320.0); miny=-0.5; sday=relday; if relday < 0 or relday > 150 then do; miny = .; sday=.; end; output; end;

patient="Patient 6416: White Male Age 64; Drug: A"; do relday = -25 to 70 by 15; alat = 1.5 + 2 * sin(3.14 * (relday+25) / 540.0); asat = 1.0 + 1 * sin(3.14 * (relday+25) / 540.0); alkph = 0.5 + 2 * sin(3.14 * (relday+25) / 360.0); biltot = 1.5 + 1 * sin(3.14 * (relday+25) / 360.0); miny=-0.5; sday=relday; if relday < 0 or relday > 60 then do; miny = .; sday=.; end; output; end;

patient="Patient 6850: White Male Age 51; Drug: A"; do relday = -25 to 175 by 25; alat = 2 + 1 * sin(3.14 * (relday+25) / 90); asat = 1.2 + 1 * sin(3.14 * (relday+25) / 100); alkph = 0.7 + 0.5 * sin(3.14 * (relday+25) / 120); biltot = 0.3 + 0.2 * sin(3.14 * (relday+25) / 110); miny=-0.5; sday=relday; if relday < 0 or relday > 150 then do; miny = .; sday=.; end; output; end;

patient="Patient 6969: White Female Age 48; Drug: B"; do relday = -25 to 175 by 25; alat = 0.5 + 1.5 * sin(3.14 * (relday+25) / 540); asat = 0.6 + 1.2 * sin(3.14 * (relday+25) / 480); alkph = 0.7 + 1 * sin(3.14 * (relday+25) / 600); biltot = 0.3 + 1 * sin(3.14 * (relday+25) / 500); miny=-0.5; sday=relday; if relday < 0 or relday > 150 then do; miny = .; sday=.; end; output; end; run;

ods listing close; ods html file='riskpanel.html' path='.' style=statistical ; ods graphics / reset width=800px height=600px imagename='RiskPanel' imagefmt=gif ;

title "Liver Function Tests by Trial Day: At Risk Patients"; footnote1 ' '; footnote2 j=l italic height=8pt " For ALAT, ASAT and Alkaline Phosphatase, the Clinical Concern Level is 2 ULN;"; footnote3 j=l italic height=8pt " For Bilirubin Total, the CCL is 1.5 ULN: " "where ULN is the Upper Level of Normal";

proc sgpanel data=labs cycleattrs; panelby patient / novarname; series x=relday y=alat / markers lineattrs=(thickness=2px pattern=solid); series x=relday y=asat / markers lineattrs=(thickness=2px pattern=solid); series x=relday y=alkph / markers lineattrs=(thickness=2px pattern=solid); series x=relday y=biltot / markers lineattrs=(thickness=2px pattern=solid); band x=sday lower=miny upper=4.5 / transparency=0.8 legendlabel='Trial Duration'; refline 1 1.5 2 / axis=Y lineattrs=(pattern=dash); colaxis min=-50 max= 200 offsetmin=.1 display=(nolabel); rowaxis label="Upper Limit Normal"; run; ods html close; ods listing; %ENDCODE%

Reference:

Schwartz, Susan. 2009 \x93Clinical Trial Reporting Using SAS/GRAPH\xAE SG Procedures.\x94 Proceedings of the SAS Global Forum 2009 Conference. Cary, NC: SAS Institute Inc. Available at http://support.sas.com/resources/papers/proceedings09/174-2009.pdf.