Tags:
create new tag
, view all tags, tagging instructions
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)



Example 1:

Click on image to enlarge.

Click for Code Example1

Code (Example 1 ):

%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;
 ;



Example 2:

Click on image to enlarge.

Click for Code Example 2

Code (Example 2 ):

%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;
 ;



Example 3:

Click on image to enlarge.

Click for Code Example 3

Code (Example 3 ):

%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;
 ;

Example 4

Figure_6_200.PNG

Click for Code Example 4

Code (Example 4 ):

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;

Reference:

Schwartz, Susan. 2009 “Clinical Trial Reporting Using SAS/GRAPH® SG Procedures.” 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.

ReferencedImageGraphicsForm edit

Title Line Plot Examples
Contributor/Email fabrice.bancken@novartis.com<fabrice.bancken@novartis.com>;
Disclaimer The views expressed within CTSpedia are those of the author and must not be taken to represent policy or guidance on the behalf of any organization or institution with which the author is affiliated.
Permission Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT OLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Reference Image Bancken_LinePlotExample1_200.png
Topic revision: r5 - 09 Jul 2012 - 14:41:31 - MaryBanach
 

Copyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding CTSPedia? Send feedback