8.5 Custom Tabular Reports with PROC REPORT & PROC TABULATE
Key Takeaways
- PROC REPORT combines features of PROC PRINT, PROC MEANS, and PROC TABULATE, using a COLUMN statement to define columns and DEFINE statements for usage types.
- The DEFINE statement usage types in PROC REPORT include DISPLAY, ORDER, GROUP, ANALYSIS, and ACROSS.
- The ACROSS usage type in PROC REPORT transposes unique values of a categorical variable into horizontal column headers across the report.
- PROC TABULATE builds multi-dimensional tables using page, row, and column expressions separated by commas (page, row, column).
- In PROC TABULATE syntax, the asterisk (*) operator nests variables within table dimensions, while a blank space concatenates variables side-by-side.
8.5 Custom Tabular Reports with PROC REPORT & PROC TABULATE
When standard row listings from PROC PRINT or basic summary outputs from PROC MEANS do not satisfy complex business reporting requirements, Base SAS provides two sophisticated custom reporting procedures: PROC REPORT and PROC TABULATE. Both procedures can calculate summary statistics, format hierarchical matrix structures, and produce publication-ready reports across ODS destinations. Mastering their statements, usage types, dimension operators, and compute block rules is a key focus area on the SAS Certified Specialist Base Programming exam.
1. PROC REPORT Architecture & Mechanics
PROC REPORT combines the detail-listing capabilities of PROC PRINT with the statistical summary features of PROC MEANS and the formatting power of PROC TABULATE in a single unified interface.
Essential Statements in PROC REPORT:
COLUMN variable-list;: A mandatory statement that specifies all variables and calculated items to include in the report, strictly defining their left-to-right visual column sequence.DEFINE variable / usage-type 'column-header' options;: Specifies how a particular variable is processed, its header label, formatting, and alignment.
proc report data=sashelp.shoes;
column Region Product Sales Returns Profit;
define Region / group "Sales Region";
define Product / display "Product Line";
define Sales / analysis sum format=dollar14.2 "Gross Sales";
run;
2. PROC REPORT DEFINE Usage Types
The usage type specified after the slash (/) in a DEFINE statement dictates how PROC REPORT evaluates and renders that column during report execution:
| Usage Type | Behavioral Description & Exam Rules |
|---|---|
DISPLAY | Displays raw observation values for each row (like PROC PRINT). Default usage for character variables if no grouping or ordering occurs. |
ORDER | Displays detail rows ordered by the formatted values of the variable, but suppresses repeating duplicate values in consecutive rows for clean visual layout. |
GROUP | Collapses observations sharing identical formatted values into a single summary row. Numeric variables in the report are automatically summarized across the group. |
ANALYSIS | Calculates a statistic for a numeric variable (default statistic is SUM). Default usage for numeric variables in PROC REPORT. |
ACROSS | Pivots/transposes unique values of a categorical variable horizontally into column headers across the top of the report matrix. |
COMPUTED | Defines a new column whose values are calculated dynamically using DATA step expressions inside a COMPUTE block. |
/* Demonstrating ACROSS vs GROUP */
proc report data=sashelp.shoes;
column Region Product, (Sales Returns);
define Region / group;
define Product / across;
define Sales / analysis sum format=dollar12.;
define Returns / analysis sum format=dollar12.;
run;
Exam Tip - ORDER vs. GROUP:
ORDERpreserves every detail row in the dataset (it merely suppresses repeating text in column 1).GROUPcollapses multiple detail rows into a single aggregated summary row!
3. Compute Blocks in PROC REPORT
PROC REPORT allows custom programming logic using COMPUTE ... ENDCOMPUTE blocks to calculate new column values, insert text lines, or format cells conditionally.
proc report data=sashelp.shoes;
column Region Sales Returns NetSales;
define Region / group;
define Sales / analysis sum;
define Returns / analysis sum;
define NetSales / computed format=dollar14.2 "Net Sales";
/* Compute block for target computed column */
compute NetSales;
NetSales = Sales.sum - Returns.sum;
endcompute;
run;
Rules for Compute Blocks:
- Referencing Variables: When referencing an
ANALYSISvariable inside a compute block, specify both the variable name and statistic (e.g.,Sales.sumorReturns.mean). - Execution Timing: Compute blocks execute during the report formatting phase after data grouping and statistic calculations are completed.
LINEStatement: Inserts custom text lines above or below summary breaks (e.g.,compute after Region; line "End of Region"; endcompute;).
4. PROC TABULATE Architecture & Dimensions
PROC TABULATE constructs complex multi-dimensional tables (hierarchical tables with page, row, and column dimensions) using concise expression syntax.
Core Statements in PROC TABULATE:
CLASS variable-list;: Identifies categorical variables used for grouping into row, column, or page headers.VAR variable-list;: Identifies numeric analysis variables to be summarized.TABLE <page-expression,> <row-expression,> column-expression / options;: Defines the structural layout and dimensions of the report table.
proc tabulate data=sashelp.shoes;
class Region Product;
var Sales;
table Region, Product * Sales * mean;
run;
5. Dimension Syntax and Operators in PROC TABULATE
The TABLE statement uses specific punctuation operators to construct table dimensions:
1. Dimension Separator: The Comma (,)
Commas separate table dimensions in the TABLE statement. A table can have up to 3 dimensions:
- 1 Dimension:
TABLE column-expression; - 2 Dimensions:
TABLE row-expression , column-expression; - 3 Dimensions:
TABLE page-expression , row-expression , column-expression;
2. Nesting Operator: The Asterisk (*)
The asterisk nests elements within a dimension, placing categories inside another category.
3. Concatenation Operator: Blank Space ( )
A space concatenates elements side-by-side within the same dimension.
4. Grouping Operator: Parentheses ()
Parentheses group elements to apply an operator (such as nesting or a statistic) across multiple variables simultaneously.
5. Summary Keyword: ALL
Adding ALL creates summary total rows, columns, or pages across categorical levels.
/* Advanced PROC TABULATE Example with Nesting, Concatenation, and ALL */
proc tabulate data=sashelp.shoes;
class Region Product;
var Sales Returns;
/* Row dimension: Region concatenated with ALL */
/* Column dimension: Product nested with Sales and Returns statistics */
table Region all,
Product * (Sales*sum Returns*mean)
/ box="Sales Analysis" misstext="N/A";
run;
BOX="text": Customizes the top-left empty corner box of a 2-D table.MISSTEXT="text": Replaces blank missing value cells with custom text (e.g.,N/Aor0).KEYLABELStatement: Relabels default statistic keywords (e.g.,keylabel sum="Total" mean="Average";).
6. Comprehensive Comparison of PROC REPORT & PROC TABULATE
| Feature | PROC REPORT | PROC TABULATE |
|---|---|---|
| Primary Layout | Column-oriented listings & summaries | Multi-dimensional matrix tables |
| Categorical Variable Declaration | DEFINE var / GROUP or ACROSS | CLASS variable-list; |
| Analysis Variable Declaration | DEFINE var / ANALYSIS | VAR variable-list; |
| Custom Calculations | COMPUTE ... ENDCOMPUTE blocks | Pre-defined statistics keywords only |
| Grand Totals & Subtotals | BREAK / RBREAK statements | ALL keyword in TABLE expression |
Which DEFINE statement usage type in PROC REPORT transposes the unique values of a categorical variable into horizontal column headers across the report?
In PROC TABULATE TABLE statement syntax, what operator is used to separate table dimensions (e.g., separating row expressions from column expressions)?
What is the key functional difference between the ORDER usage type and the GROUP usage type in PROC REPORT?
A programmer writes the following PROC TABULATE step: proc tabulate data=sashelp.shoes; class Region Product; var Sales; table Region * Product, Sales * sum; run; What does the asterisk (*) operator do between Region and Product in the row dimension?