TEMPLATE Procedure: Creating Crosstabulation Table Templates

Example 2: Creating a Crosstabulation Table Template with a Customized Legend

Features:

crosstabs-attributes statements

CELLVALUE statement

DEFINE CELLVALUE statement:
CELLSTYLE AS statement
END statement
FORMAT= attribute
HEADER= attribute
LABEL= attribute
DEFINE HEADER statement:
END statement
SPACE= attribute
STYLE= attribute
TEXT statement
DEFINE FOOTER statement:
END statement
DYNAMIC statement
SPACE= attribute
STYLE= attribute
TEXT statement

END statement

FOOTER statement

HEADER statement

NOTES statement

Other features:
Other ODS features:
ODS HTML statement
ODS PATH statement
DEFINE STYLE statement

Details

The following example creates a new crosstabulation table template for the CrossTabFreqs table. The template has the following features:
  • a legend with customized text
  • modified headers and footers
  • variable labels used in headers
  • modified table regions
  • customized styles for cellvalues

Program

 Proc Format;
   Value Govtfmt -3='Council Manager'
                  0='Commission'
                  3='Mayor Council'
                 .N='Not Applicable'
                  .='   ?';
   Value Robfmt   1='100 or  Less'
                  2='101-200'
                  3='201-300'
                  4='Over 300'
                 .N='Not     Known'
                  .='   ?';
   Value colfg   1='yellow'
                  2='red'
                  3='blue'
                  4='purple'
                 .N='green'
                  .='black'
                  other='black';
   Value rowfg   -3='red'
                  0='purple'
                  3='blue'
                 .N='green'
                  .='black'
                  other='black';
run;

data gov;
   Label Citygovt='City Government Form'
        Robgrp='Number of Meetings Scheduled';
   Input Citygovt Robgrp Weight;  Missing N;
   Format Citygovt Govtfmt. Robgrp Robfmt.;
   LOOP: OUTPUT; WEIGHT=WEIGHT-1; IF WEIGHT>0 THEN GOTO LOOP;
   DROP WEIGHT;
datalines;
0 1  6
0 3  3
0 2  7
0 4  5
N N 10
-3 1 47
-3 3 49
-3 2 63
-3 4 52
. 2  1
3 1 31
3 2 37
3 3 27
3 4 55
3 .  1
;
ods path (prepend) work.templat(update);
proc template;
   define crosstabs Base.Freq.CrossTabFreqs;
      notes "Crosstabulation table with legend";
      rows_header=RowsHeader cols_header=ColsHeader;
      label = "Frequency Counts and Percentages";
      grand_total_style=data {fontweight=bold};
   define header ControllingFor;
      dynamic StratNum StrataVariableNames StrataVariableLabels;
      text "Controlling for" StrataVariableNames / StratNum > 0;
      style=header;
      end;
   define header RowsHeader;
      text _ROW_LABEL_ / _ROW_LABEL_ ^= '';
      text _ROW_NAME_;
      space=0;
      style=header;
      cindent=';';
      end;
   define header ColsHeader;
      text _COL_LABEL_ / _COL_LABEL_ ^= '';
      text _COL_NAME_;
      space=1;
      style=header;
      cindent=';';
      end;
   define footer TableOf;
      notes 'NoTitle is 1 if the NOTITLE option was specified.';
      dynamic StratNum NoTitle;
      text "Table " StratNum 3. " of " _ROW_LABEL_ " by " _COL_LABEL_ / NoTitle= 0
          & StratNum > 0 & _ROW_LABEL_ ^= '' & _COL_LABEL_ ^= '';
      text "Table " StratNum 3. " of " _ROW_LABEL_ " by " _COL_NAME_  / NoTitle= 0
          & StratNum > 0 & _ROW_LABEL_ ^= ''                    ;
      text "Table " StratNum 3. " of " _ROW_NAME_  " by " _COL_LABEL_ / NoTitle= 0
          & StratNum > 0 & _COL_LABEL_ ^= '';
      text _ROW_LABEL_ " by " _COL_LABEL_ /  NoTitle = 0 &  _ROW_LABEL_ ^=''
          & _COL_LABEL_ ^= '';
      text _ROW_LABEL_ " by " _COL_NAME_  /  NoTitle = 0 &  _ROW_LABEL_ ^='';
      text _ROW_NAME_  " by " _COL_LABEL_ /  NoTitle = 0 &  _COL_LABEL_ ^='';
      text "Table " StratNum 3. " of " _ROW_NAME_  " by " _COL_NAME_  / NoTitle= 0
          & StratNum > 0;
      text _ROW_NAME_  " by " _COL_NAME_ / NoTitle = 0;
      style=header;
      end;
   define footer Missing;
      dynamic FMissing;
      text "Frequency Missing = " FMissing -12.99 / FMissing ^= 0;
      space=1;
      style=header;
      end;

   define footer NoObs;
      dynamic SampleSize;
      text "Effective Sample Size = 0" / SampleSize = 0;
      space=1;
      style=header;
      end;
   define cellvalue Frequency;
      header="Frequency";
      format=BEST7.;
      label="Frequency Count";
      data_format_override=on print=on;
      end;

   define cellvalue Expected;
      header="Expected";
      format=BEST6.;
      label="Expected Frequency";
      data_format_override=on print=on;
      end;

   define cellvalue Deviation;
      header="Deviation";
      format=BEST6.;
      label="Deviation from Expected Frequency";
      data_format_override=on print=on;
      end;

   define cellvalue CellChiSquare;
      header="Cell Chi-Square";
      format=BEST6.;
      label="Cell Chi-Square";
      print=on;
      end;

   define cellvalue TotalPercent;
      header="Total Percent";
      format=6.2;
      label="Percent of Total Frequency";
      print=on;
      end;

   define cellvalue Percent;
      header="Percent";
      format=6.2;
      label="Percent of Two-Way Table Frequency";
      print=on;
      cellstyle _val_ > 20.0 as {color=#BF6930};
      end;

   define cellvalue RowPercent;
      header="Row Percent";
      format=6.2;
      label="Percent of Row Frequency";
      print=on;
      end;

   define cellvalue ColPercent;
      header="Column Percent";
      format=6.2;
      label="Percent of Column Frequency";
      print=on;
      end;

   define cellvalue CumColPercent;
      header="Cumulative Column Percent";
      format=6.2;
      label="Cumulative Percent of Column Frequency";
      print=on;
end;
      header ControllingFor;
      footer TableOf NoObs Missing;
   cellvalue
      Frequency Expected Deviation
      CellChiSquare TotalPercent Percent
      RowPercent ColPercent CumColPercent;
end;
run;
title "City Government Form by Number of Meetings Scheduled";
ods html file='MyCrosstabsTableLegend.html'  style=ocean;
proc freq;
   tables citygovt*robgrp / missprint;
run;
ods html close;

Program Description

Create the user-defined formats and the data set. The FORMAT procedure creates two user-defined formats that can be used in the crosstabulation template. The DATA step creates the Gov data set.
 Proc Format;
   Value Govtfmt -3='Council Manager'
                  0='Commission'
                  3='Mayor Council'
                 .N='Not Applicable'
                  .='   ?';
   Value Robfmt   1='100 or  Less'
                  2='101-200'
                  3='201-300'
                  4='Over 300'
                 .N='Not     Known'
                  .='   ?';
   Value colfg   1='yellow'
                  2='red'
                  3='blue'
                  4='purple'
                 .N='green'
                  .='black'
                  other='black';
   Value rowfg   -3='red'
                  0='purple'
                  3='blue'
                 .N='green'
                  .='black'
                  other='black';
run;

data gov;
   Label Citygovt='City Government Form'
        Robgrp='Number of Meetings Scheduled';
   Input Citygovt Robgrp Weight;  Missing N;
   Format Citygovt Govtfmt. Robgrp Robfmt.;
   LOOP: OUTPUT; WEIGHT=WEIGHT-1; IF WEIGHT>0 THEN GOTO LOOP;
   DROP WEIGHT;
datalines;
0 1  6
0 3  3
0 2  7
0 4  5
N N 10
-3 1 47
-3 3 49
-3 2 63
-3 4 52
. 2  1
3 1 31
3 2 37
3 3 27
3 4 55
3 .  1
;
Establish the ODS path. The ODS PATH statement specifies the locations to write to or read from when you create the PROC TEMPLATE templates.
ods path (prepend) work.templat(update);
Create the crosstabulation template Base.Freq.CrossTabFreqs.The DEFINE statement creates the crosstabulation template Base.Freq.CrossTabFreqs in the first template store in the path for which you have Write access. The NOTES statement provides information about the crosstabulation table.
proc template;
   define crosstabs Base.Freq.CrossTabFreqs;
      notes "Crosstabulation table with legend";
Specify a row header, a column header, and a label for the table. The ROWS_HEADER= style attribute specifies RowsHeader as the header for rows. The COLS_HEADER= style attribute specifies ColsHeader as the header for columns. The LABEL= attribute specifies a label for the crosstabulation template. The GRAND_TOTAL_STYLE= changes the FontWeight style attribute in the Data style element to bold. This change affects the values in the rightmost column of the last row in the table.
      rows_header=RowsHeader cols_header=ColsHeader;
      label = "Frequency Counts and Percentages";
      grand_total_style=data {fontweight=bold};
Create the ControllingFor header template. The DEFINE HEADER statement and its attributes create the header template ControllingFor. The DYNAMIC statement declares dynamic variables so that they can be used in expressions. The TEXT statement specifies the text of the header by using dynamic variables that represent label variables and names. In this example, the expression in the TEXT statement resolves to false, so the ControllingFor header does not show up in the output. The STYLE= attribute specifies style information for the headers.
   define header ControllingFor;
      dynamic StratNum StrataVariableNames StrataVariableLabels;
      text "Controlling for" StrataVariableNames / StratNum > 0;
      style=header;
      end;
Create the RowsHeader header template. The DEFINE HEADER statement creates the header RowsHeader, which is specified by the preceding ROWS_HEADER= style attribute. The TEXT statements specify the text of the header by using dynamic variables that represent label variables and names. The first TEXT statement uses an expression to determine whether a label is assigned to the row variable. If there is no label, the next TEXT statement is used, which specifies the row name. In this example there is a row label for the row variable, so in the output, _ROW_LABEL_ resolves to "City Government Form".The STYLE= attribute specifies style information for the header. The SPACE= attribute specifies that the current header and the previous header should have one blank line between them. The CINDENT= attribute specifies that wrapped lines start at the same column as the left parenthesis.
   define header RowsHeader;
      text _ROW_LABEL_ / _ROW_LABEL_ ^= '';
      text _ROW_NAME_;
      space=0;
      style=header;
      cindent=';';
      end;
Create the ColsHeader header template. The DEFINE HEADER statement creates the header ColsHeader, which is specified by the preceding COLS_HEADER= style attribute. The TEXT statements specify the text of the header by using dynamic variables that represent label variables and names. The first TEXT statement uses an expression to determine whether a label is assigned to the variable. If there is no label, the next TEXT statement is used, which specifies the row name. In this example there is a column label, so in the output, _COL_LABEL_ resolves to "Number of Meetings Scheduled".The STYLE= attribute specifies style information for the header. The SPACE= attribute specifies that the current header and the previous header should have one blank line between them. The CINDENT= attribute specifies that wrapped lines start at the same column as the left parenthesis.
   define header ColsHeader;
      text _COL_LABEL_ / _COL_LABEL_ ^= '';
      text _COL_NAME_;
      space=1;
      style=header;
      cindent=';';
      end;
Create the TableOf footer template. The DEFINE FOOTER statement and its attributes create the footer template TableOf, which is specified by the FOOTER statement later on in the program. The TEXT statements specify the text of the header by using dynamic variables that represent label variables and names, the NOTITLE option, and the current stratum number. The TEXT statements use expressions with these variables to determine which text is displayed. Only the TEXT statements that have a true expression are displayed in the output. In this example, the only text statement that has a true expression is the fourth TEXT statement, and the text resolves to: " City Government Form by Number of Meetings Scheduled".
   define footer TableOf;
      notes 'NoTitle is 1 if the NOTITLE option was specified.';
      dynamic StratNum NoTitle;
      text "Table " StratNum 3. " of " _ROW_LABEL_ " by " _COL_LABEL_ / NoTitle= 0
          & StratNum > 0 & _ROW_LABEL_ ^= '' & _COL_LABEL_ ^= '';
      text "Table " StratNum 3. " of " _ROW_LABEL_ " by " _COL_NAME_  / NoTitle= 0
          & StratNum > 0 & _ROW_LABEL_ ^= ''                    ;
      text "Table " StratNum 3. " of " _ROW_NAME_  " by " _COL_LABEL_ / NoTitle= 0
          & StratNum > 0 & _COL_LABEL_ ^= '';
      text _ROW_LABEL_ " by " _COL_LABEL_ /  NoTitle = 0 &  _ROW_LABEL_ ^=''
          & _COL_LABEL_ ^= '';
      text _ROW_LABEL_ " by " _COL_NAME_  /  NoTitle = 0 &  _ROW_LABEL_ ^='';
      text _ROW_NAME_  " by " _COL_LABEL_ /  NoTitle = 0 &  _COL_LABEL_ ^='';
      text "Table " StratNum 3. " of " _ROW_NAME_  " by " _COL_NAME_  / NoTitle= 0
          & StratNum > 0;
      text _ROW_NAME_  " by " _COL_NAME_ / NoTitle = 0;
      style=header;
      end;
Create additional footer templates. Each of these DEFINE FOOTER statements and each of its attributes creates a footer template. To apply these footers to your output, you must specify them in the FOOTER statement. The DYNAMIC statements declare the dynamic variables FMissing, Stratnum, NoTitle, and SampleSize, so that they can be used in the TEXT statements. The TEXT statements conditionally select text to use as footers. In the first TEXT statement, the expression is true, because FMissing is not 0. Therefore, the first TEXT statement is displayed in the output. In the second TEXT statement, the expression resolves to false, and the NoObs footer does not appear in the output. The STYLE attribute specifies style information for the footers. The SPACE attribute specifies that the current footer and the previous footer should have one blank line between them.
   define footer Missing;
      dynamic FMissing;
      text "Frequency Missing = " FMissing -12.99 / FMissing ^= 0;
      space=1;
      style=header;
      end;

   define footer NoObs;
      dynamic SampleSize;
      text "Effective Sample Size = 0" / SampleSize = 0;
      space=1;
      style=header;
      end;
Create the cellvalue definitions. The DEFINE CELLVALUE statements define the values that appear in the cells of the crosstabulation table. The HEADER= attribute specifies the text that appears in the legend. The LABEL= attribute specifies the label for the data set column that corresponds to the cellvalue. The LABEL= attribute affects only the Output destination. The DATA_FORMAT_OVERRIDE=ON attribute specifies to use the format specified in the data component. The PRINT=ON attribute causes the cellvalue to appear in the table. The CELLSTYLE AS statement uses expressions to conditionally set the style element of the cells according to the values of the variables for the Percent cellvalue. The _VAL_ variable represents the value of a cell. Therefore, in this example, if the value in a cell is less than ten, then the font color for the DataStrong style element is green. If the value in the cell is greater than twenty, the font color is #BF6930.
   define cellvalue Frequency;
      header="Frequency";
      format=BEST7.;
      label="Frequency Count";
      data_format_override=on print=on;
      end;

   define cellvalue Expected;
      header="Expected";
      format=BEST6.;
      label="Expected Frequency";
      data_format_override=on print=on;
      end;

   define cellvalue Deviation;
      header="Deviation";
      format=BEST6.;
      label="Deviation from Expected Frequency";
      data_format_override=on print=on;
      end;

   define cellvalue CellChiSquare;
      header="Cell Chi-Square";
      format=BEST6.;
      label="Cell Chi-Square";
      print=on;
      end;

   define cellvalue TotalPercent;
      header="Total Percent";
      format=6.2;
      label="Percent of Total Frequency";
      print=on;
      end;

   define cellvalue Percent;
      header="Percent";
      format=6.2;
      label="Percent of Two-Way Table Frequency";
      print=on;
      cellstyle _val_ > 20.0 as {color=#BF6930};
      end;

   define cellvalue RowPercent;
      header="Row Percent";
      format=6.2;
      label="Percent of Row Frequency";
      print=on;
      end;

   define cellvalue ColPercent;
      header="Column Percent";
      format=6.2;
      label="Percent of Column Frequency";
      print=on;
      end;

   define cellvalue CumColPercent;
      header="Cumulative Column Percent";
      format=6.2;
      label="Cumulative Percent of Column Frequency";
      print=on;
end;
Specify header and footer templates. The HEADER statement specifies the header templates that are applied to your output. The FOOTER statement specifies the footer templates that are applied to your output. In order for any of the headers and footers that were defined by a DEFINE statement to appear in your output, they must be specified by the FOOTER or HEADER statement.
      header ControllingFor;
      footer TableOf NoObs Missing;
Specify cellvalues and their order. The CELLVALUE statement specifies which cellvalues will appear in the table and the order. In this example, all of the cellvalues that you created appear in the table, in the order specified by the CELLVALUE statement.
   cellvalue
      Frequency Expected Deviation
      CellChiSquare TotalPercent Percent
      RowPercent ColPercent CumColPercent;
end;
run;
Specify a title, create the HTML output, and specify the name of the HTML file. The TITLE statement provides a title for the output. The ODS HTML statement with the STYLE= option specifies the style template Ocean for the output.
title "City Government Form by Number of Meetings Scheduled";
ods html file='MyCrosstabsTableLegend.html'  style=ocean;
Create the crosstabulation table. The FREQ procedure creates a Citygovt by Robgrp crosstabulation table.
proc freq;
   tables citygovt*robgrp / missprint;
run;
Close the HTML destination. The ODS HTML CLOSE statement closes the HTML destination and all the files that are open for that destination.
ods html close;

Output

Output Using Customized Crosstabulation Table Template
Output Using Customized Crosstabulation Table Template
Output Using Default Crosstabulation Table
Output Using Default Crosstabulation Table