Graphically Speaking

Advanced ODS Graphics: Axis tables in PROC SGPLOT and the GTL

Axis tables enable you to combine tabular and graphical information into a single display. I love the axis table. My involvement with the axis table dates back over 30 years to its ancient predecessor, the ASCII bar chart. In the mid 1980s, I created a table in PROC CORRESP consisting of 5 columns of numbers and a series of asterisks to graphically show the percentage column. In Version 7, as ODS was being developed and we supported destinations other than LISTING, this was among the last tables that the ODS team provided options to create. A few years ago, I happily replaced my ASCII bar chart with a graph using axis tables. Since then, I have also added axis tables to replace ASCII bar charts in PROC REG. Axis tables are also used in PROC LIFETEST and have numerous uses in clinical graphs. Sanjay has blogged about them often. Today, I am going to discuss some differences between axis tables in PROC SGPLOT and in the GTL. With only a little more work than writing PROC SGPLOT code, you can access some of the increased flexibility of the axis table in the GTL.

The following steps show how to make a simple graph that consists of an axis table and a scatter plot. The axis table consists of four groups of observations. Each group has a header and is separated from adjacent groups by blank lines.

data x(keep=n line value);
do g = 1 to 4;
Value = ‘Head ‘;
Line = catx(‘ ‘, ‘Greater Than’, 10 * (g – 1), ‘A0A0’x);
value = ‘Body’;
do i = 1 to 10;
k + 1;
n = k;
line = ‘A0A0A0’x || put(k, words30.);
value = ‘Blank’;
line = repeat(‘A0’x, g – 1);
n = .;
if g lt 4 then output;

data attrmap;
id=’mymap’; textcolor=’Black’;
value=’Head ‘; textsize=6; textweight=’bold ‘; output;
value=’Body ‘; textsize=5; textweight=’normal’; output;
value=’Blank’; textsize=1; output;

ods graphics on / height=500 width=250;
proc sgplot data=x noborder noautolegend dattrmap=attrmap tmplout=’temp.temp’;
yaxistable line / position=left textgroup=value textgroupid=mymap;
scatter y=line x=n / x2axis markerattrs=(symbol=circlefilled);
yaxis reverse display=none;
xaxis display=(noticks nolabel novalues);
x2axis grid display=(noticks nolabel) valueattrs=(size=6px);
label line=’00’x;
scatter y=line x=n / markerattrs=(size=0);

Advanced ODS Graphics: Axis tables in PROC SGPLOT and the GTL

The TMPLOUT= option writes the underlying template that PROC SGPLOT creates to a file. After adding indentation, the template is as follows:

proc template;
define statgraph sgplot;
begingraph / collation=binary;
DiscreteAttrVar attrvar=MYMAP_VALUE var=VALUE
DiscreteAttrMap name=”__ATTRMAP__MYMAP” /;
Value “Head” / textattrs=(color=CX000000 weight=bold);
Value “Body” / textattrs=(color=CX000000 weight=normal);
Value “Blank” / textattrs=(color=CX000000 weight=normal);
layout lattice / columnweights=preferred rowweights=preferred
columndatarange=union rowdatarange=union columns=2;
Layout Overlay / yaxisopts=(reverse=true display=none
type=discrete) walldisplay=none
yaxisopts=(display=none griddisplay=off
y2axisopts=(display=none griddisplay=off
AxisTable Value=Line Y=Line / labelPosition=min
textGroup=MYMAP_VALUE Display=(Label);
layout overlay / cycleattrs=true walldisplay=(fill)
xaxisopts=(display=(line) type=linear)
yaxisopts=(reverse=true display=none
x2axisopts=(display=(tickvalues line)
TickValueAttrs=(Size=6px) type=linear
ScatterPlot X=n Y=Line / subpixel=off primary=true
xaxis=x2 Markerattrs=(Symbol=CIRCLEFILLED)
LegendLabel=”” NAME=”SCATTER”;
ScatterPlot X=n Y=Line / subpixel=off Markerattrs=(Size=0)
LegendLabel=”” NAME=”SCATTER1″;

You can use it to create the same graph by calling PROC SGRENDER:

proc sgrender data=x template=sgplot;
label line=’00’x;

The PROC SGPLOT YAXISTABLE statement is as follows:

yaxistable line / position=left textgroup=value textgroupid=map;

The statement in the PROC SGPLOT graph template is:

AxisTable Value=Line Y=Line / labelPosition=min
textGroup=MAP_VALUE Display=(Label);

The YAXISTABLE statement requires one variable. This is the variable that is displayed and it provides the coordinates for that display. In contrast, the AXISTABLE statement in the GTL has two variables. You can specify coordinates in the Y= option that are different from the values that are displayed.

The PROC SGPLOT example works because every line—every Y= value in the GTL—has a unique value. In particular, the first blank line consists of one nonbreaking space (‘A0’x), the second blank line consists of two nonbreaking spaces (‘A0A0’x), and the third blank line consists of three nonbreaking spaces (‘A0A0A0’x). You must use unique patterns of nonbreaking spaces for this example to work. This could be come problematic in more complicated reports in which some lines might be the same.

PROC SGPLOT generates a LAYOUT LATTICE block that contains two LAYOUT OVERLAY blocks. The option COLUMNWEIGHTS=PREFERRED specifies that ODS Graphics is free to set the width of the axis table and the scatter plot based on the width of the axis table. In the GTL (but not in PROC SGPLOT) you can explicitly control the width by specifying a vector of column weights. For example COLUMNWEIGHTS=(0.75 0.25) creates an axis table that occupies 75% of the vertical space. For advanced uses of the axis table, you might want to both explicitly control the Y coordinate and the axis table width, which means you need to use the graph template. Fortunately, PROC SGPLOT writes graph templates for you that you can save and modify.

This step creates a modified input data set:

data y;
set x;
RowID + 1;
if value eq ‘Blank’ then line = ‘ ‘;

This data set has a RowID variable that contains the row number. Blank lines consist of ordinary blanks and are no longer unique.

You can use a DATA step to edit the graph template. The following step (optionally) changes the name to ‘MyAxisTemplate’, specifies weights to give both the axis table and the scatter plot 50% of the vertical space, and modifies the three Y=LINE options to specify Y=RowID.

data _null_;
infile ‘temp.temp’;
_infile_ = tranwrd(_infile_, ‘sgplot’, ‘MyAxisTemplate’);
_infile_ = tranwrd(_infile_, ‘columnweights=preferred’,
‘columnweights=(0.5 0.5)’);
_infile_ = tranwrd(_infile_, ‘Y=Line’, ‘Y=rowid’);
call execute(_infile_);

proc sgrender data=y template=MyAxisTemplate;
label line=’00’x;

Except for the change in width, these steps create the same graph as is shown above. By modifying the graph template, you can control the row coordinates and the width of each panel, which gives you greater flexibility in making complicated reports.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s