Skip to content

Paneled Box Plot

Shane Rosanbalm edited this page Mar 22, 2017 · 13 revisions

Contents

  1. The Goal
  2. Dummy Data
  3. Vbox Only
  4. Add Panels
  5. Make Panels Nice
  6. Make Axes Nice
  7. Style Modifications
  8. Fix Colaxis

The Paneled Box Plot will be developed in several steps. A succinct version of the code is available here.

The Goal

On this page, we will walk through the process of creating a paneled box plot, paneled by visit, with treatment comparisons within each visit.

paneled box plot the goal

Dummy Data

The dummy data used to produce this plot was created with the following data step. This data step is only included for the sake of completeness. Do not read, study, or obsess over this data step!

data derive.adlb;
   length paramcd $8 param $100;
   do paramcd = "ALT", "AST";
      if paramcd = "ALT" then 
         param = "Alanine Aminotransferase (IU/L)";
      else if paramcd = "AST" then
         param = "Aspartate Transaminase (IU/L)";
      do trtpn = 1 to 4;
         trtp = propcase(put(trtpn,words.));
         do subjid = 1 to 40;
            do avisitn = 0, 1, 2, 4, 6, 8 to 24 by 4;
               length avisit $20;
               if avisitn = 0 then avisit = "B/L";
               else avisit = 'Week ' || strip(put(avisitn,best.));
               aval = 45 + rannor(1)*(1+avisitn/24)*(trtpn/4);
               if ranuni(1) < (50-avisitn)/50 then output;
            end;
         end;
      end;
   end;
run;

paneled box plot dummy data

Vbox Only

In this step, we will learn how to produce a "vbox only" plot.

paneled box plot vbox only

In order to create a vbox (vertical box) plot, we first subset and sort our data. We sort it by avisitn to order the panels. We sort by trtpn to order the treatments within each panel.

proc sort data=derive.adlb out=pbp00;
   by avisitn trtpn;
   where paramcd = "ALT";
run;

If we are going to produce a figure for a commercial study, it is probably going to need to be saved as an RTF file. The typical options, ods graphics, and ods rtf statements that surround the sgplot code are as follows:

options 
   nonumber 
   nodate 
   orientation=landscape
   ;

ods graphics / 
   noborder 
   height=4in 
   width=8in
   outputfmt=png
   ;

ods results off;
ods listing close;
ods rtf file="&PgmDir\vbox_only.rtf";

   <<sgplot portion>>

ods rtf close;
ods listing;
ods results on;

The <<sgplot portion>> contains a vbox statement along with a couple of basic options.

proc sgplot data=pbp00;
   *--- draw box plots ---;
   vbox aval /
      category=trtpn
      fillattrs=(color=ltgray)
      ;
run;

paneled box plot vbox only

Notice that we used the option category instead of group. Had we used group we would have end up with a legend, which would require the use of colors (or worse, patterns) to differentiate the groups. Instead, we used category so that the trtpn values will be displayed on the xaxis.

Add Panels

An astute observer will have noticed that the above code did not produce a paneled plot. In this step, we switch from SGPLOT to SGPANEL. The vbox statement remains unaltered. We add the aptly-named panelby statement so that SGPANEL will know how to panel the data.

proc sgpanel data=pbp00;
   *--- panel structure ---;
   panelby avisitn;
   *--- draw box plots ---;
   vbox aval /
      category=trtpn
      fillattrs=(color=ltgray)
      ;
run;

paneled box plot add panels

Notice how the header labels for the panels are pretty crude. Also notice how the individual panels are drawn so large that only two can fit on a page.

Make Panels Nice

In this step we clean up the header labels and shrink the panels so that all visits fit on one page.

paneled box plot make panels nice

First we create a format for the header labels.

proc sql;
   create   table avisitn as
   select   distinct "avisitn" as fmtname, 
            avisitn as start, 
            avisit as label
   from     pbp00
   ;
quit;

proc format cntlin=avisitn;
run;

proc sql noprint;
   alter    table pbp00
   modify   avisitn format=avisitn.
   ;
quit;

Now we add a couple of options to the panelby statement.

proc sgpanel data=pbp00;
   *--- panel structure ---;
   panelby avisitn /
      rows=2
      columns=5
      novarname
      ;
   *--- draw box plots ---;
   vbox aval /
      category=trtpn
      fillattrs=(color=ltgray)
      ;
run;

paneled box plot make panels nice

The purpose of the novarname option is to prevent the header labels from including the variable name (e.g., avisitn = Week 1).

Make Axes Nice

Next we clean up the axes.

paneled box plot make axes nice

First we create a macro variable to hold the yaxis label.

proc sql noprint;
   select   distinct strip(param)
   into     :ylabel
   from     pbp00
   ;
quit;

%let ylabel = &ylabel;
%put &=ylabel;

And then we create a format to use on the xaxis values.

proc sql;
   create   table trtpn as
   select   distinct "trtpn" as fmtname, 
            trtpn as start, 
            trtp as label
   from     pbp00
   ;
quit;

proc format cntlin=trtpn;
run;

proc sql noprint;
   alter    table pbp00
   modify   trtpn format=trtpn.
   ;
quit;

The last part of this step is to add two axis statements. Notice how yaxis and xaxis from SGPLOT have become rowaxis and colaxis in SGPANEL.

proc sgpanel data=pbp00;
   panelby ...
   vbox ...
   *--- axes ---;
   rowaxis
      label="&ylabel"
      ;
   colaxis
      label="Treatment"
      ;
run;

paneled box plot make axes nice

Style Modifications

As a penultimate step, we perform some style modifications to change fonts.

paneled box plot style modifications

Changing fonts requires TEMPLATE code. Try not to have a panic attack.

proc template;
   define style styles.pbpstyle;
      parent=styles.rtf;
      class GraphFonts /
         "GraphDataFont"  = ("Courier New", 7pt)
         "GraphValueFont" = ("Courier New", 9pt)
         "GraphLabelFont" = ("Courier New",10pt)
         ;
   end;
run;

Having created this new style styles.pbpstyle, we apply it on the ods rtf statement.

ods rtf 
   style=styles.pbpstyle
   file="&PgmDir\PBP_05_style_mods.rtf"
   ;

proc sgpanel data=pbp00;
   panelby ...
   vbox ...
   rowaxis ...
   colaxis ...
run;

ods rtf close;

paneled box plot style modifications

Fix Colaxis

Unfortunately, changing the font resulted in the colaxis values being rotated. Unacceptable! We will use the fitpolicy option to fix this.

proc sgpanel data=pbp00;
   panelby ...
   vbox ...
   rowaxis ...
   colaxis
      label="Treatment"
      fitpolicy=stagger
      ;
run;

paneled box plot fix colaxis

Next page: Forest Plot with Subgroups