4.4 Accumulating Totals & Subtotals (RETAIN & Sum Statement)
Key Takeaways
At the beginning of each DATA step execution loop, SAS automatically re-initializes all newly created variables in the PDV to missing values.
The RETAIN statement overrides default re-initialization, instructing SAS to preserve a variable's stored value in the PDV across DATA step iterations.
A Sum Statement (variable + expression;) implicitly retains the target variable, initializes its value to 0 before the first iteration, and automatically ignores missing values in the expression.
Explicit accumulation (Total = Total + Amount; with RETAIN Total 0;) will convert Total to missing (.) if Amount is missing, disrupting calculations for all subsequent rows.
BY-group processing combined with FIRST.variable and LAST.variable automatic temporary variables enables resetting accumulators at group boundaries and writing subtotal rows.
4.4 Accumulating Totals & Subtotals (RETAIN & Sum Statement)
Quick Answer: By default, at the start of each DATA step iteration, SAS resets all non-dataset variables in the Program Data Vector (PDV) to missing (
.for numeric, blank for character). To accumulate running totals or preserve values across rows, you must prevent SAS from re-initializing variables. You can achieve this using either an explicitRETAINstatement or an implicit Sum Statement (variable + expression;).
Default DATA Step Re-initialization
To understand accumulation, you must understand the PDV lifecycle:
- Input Variables (read via
SET,MERGE,MODIFY, orINPUT): Retain their values as new rows are read. - Created Variables (computed via assignment statements): Reset to missing at the top of every DATA step iteration loop.
/* FAILS TO ACCUMULATE: RunningTotal resets to missing at the start of every row! */
data work.bad_accumulator;
set work.transactions;
RunningTotal = RunningTotal + Amount; /* Always evaluates to missing (.) */
run;
In work.bad_accumulator, RunningTotal starts as missing (.). On row 1, . + Amount evaluates to missing. On row 2, SAS resets RunningTotal back to missing before executing the assignment, failing to accumulate.
The RETAIN Statement
The RETAIN statement is a compile-time directive that tells SAS not to set specified variables to missing at the beginning of each execution iteration. Instead, variables keep their previous values until new values are assigned.
Syntax
RETAIN variable-1 <initial-value-1> ... variable-n <initial-value-n>;
- Without Initial Value: Numeric variables initialize to numeric missing (
.), and character variables initialize to blank (' '). - With Initial Value: The variable is set to the specified constant before the first observation is processed.
data work.retained_total;
set work.transactions;
/* Preserve RunningTotal across rows, starting at 0 */
retain RunningTotal 0;
/* Explicit accumulator assignment using SUM function to ignore missing Amount values */
RunningTotal = sum(RunningTotal, Amount);
run;
The SAS Sum Statement
SAS provides a special abbreviated syntax designed specifically for accumulation called the Sum Statement:
variable + expression;
CRITICAL EXAM CONCEPT: Notice there is no equal sign (
=) in a Sum Statement!Total + Sales;is a Sum Statement, whereasTotal = Total + Sales;is an assignment statement.
The Four Implicit Behaviors of a Sum Statement
When SAS compiles a Sum Statement (variable + expression;), it automatically applies four rules:
- Implicit Creation: Creates
variableas a numeric variable if it does not already exist. - Implicit Initial Value: Sets
variableinitial value to0before processing the first observation. - Implicit RETAIN: Retains
variableacross all DATA step iterations. - Missing Value Immunity: Adds the value of
expressiontovariable, treating missing values inexpressionas0(ignoring missing values).
data work.sum_statement_demo;
set work.transactions;
/* Replaces RETAIN, assignment, and SUM function in one concise statement */
RunningTotal + Amount;
run;
Comparison: Explicit Retention vs. Sum Statement
| Feature / Behavior | Explicit Assignment (Total = Total + Amount; with RETAIN Total 0;) | SAS Sum Statement (Total + Amount;) |
|---|---|---|
| Syntax | Requires RETAIN statement + Total = Total + Amount; | Total + Amount; (No RETAIN, no =) |
| Default Initial Value | Missing (.) unless explicitly specified in RETAIN Total 0; | Automatically initialized to 0 |
Handling Missing Amount | Evaluates to missing (.), corrupting Total for all subsequent rows! | Treats missing Amount as 0, preserving running total |
| SAS Log Behavior on Missing | Writes diagnostic note: Missing values were generated... | Silent execution; no log warnings |
| Recommended Use Case | When custom initial values (e.g., 100) or complex logic are needed | Standard running totals and BY-group subtotals |
BY-Group Subtotal Accumulation (FIRST. and LAST.)
In business reporting, you often need to calculate running totals per category (e.g., total sales per Department or Customer). This requires combining BY group processing with accumulation logic.
Automatic Variables: FIRST.variable and LAST.variable
When a BY statement is included in a DATA step, SAS creates two temporary automatic numeric variables for each BY variable:
FIRST.variable: Equals 1 on the first observation of a BY group, and 0 for all subsequent observations in that group.LAST.variable: Equals 1 on the last observation of a BY group, and 0 for all other observations in that group.
Note: Input datasets MUST be pre-sorted by the BY variable (using
PROC SORT) before executing BY-group processing in a DATA step.
Subtotal Reset Pattern
/* Step 1: Pre-sort input data */
proc sort data=sashelp.shoes out=work.shoes_sorted;
by Region;
run;
/* Step 2: Accumulate subtotals per Region */
data work.region_subtotals;
set work.shoes_sorted;
by Region;
/* Reset accumulator on the FIRST row of each Region group */
if First.Region then RegionSales = 0;
/* Accumulate sales for rows within the Region */
RegionSales + Sales;
/* Subset: Output ONLY the LAST row of each Region group containing final subtotal */
if Last.Region;
keep Region RegionSales;
run;
Step-by-Step Execution Trace
- When
Regionchanges to'Asia',First.Regionis 1. SAS setsRegionSales = 0. RegionSales + Sales;adds the current row's sales.- Intermediate rows (
First.Region = 0,Last.Region = 0) accumulate sales without outputting becauseif Last.Region;filters them out. - On the final row of
'Asia',Last.Regionis 1. The subsettingIFevaluates to true, and SAS outputs the summary record containingRegionand the accumulatedRegionSalessubtotal.
What are the four implicit characteristics of a SAS Sum Statement (Count + 1; or Total + Sales;)?
It implicitly retains the target variable, initializes it to 0, adds the expression result, and ignores missing values in the expression.
It re-initializes the variable to missing each iteration, converts character strings to numbers, formats the variable, and outputs to log.
It executes only during compilation, requires a preceding RETAIN statement, creates an index, and sets variable length to 8 bytes.
It requires BY-group processing, sets missing values to zero in the output dataset, executes a PROC step, and creates FIRST. and LAST. flags.
Consider the following DATA step:
data work.summary;
set work.sales;
by Department;
if First.Department then SalesTotal = 0;
SalesTotal + Revenue;
if Last.Department;
run;
What is the role of if Last.Department; in this program?
It resets SalesTotal to missing at the end of each department.
It acts as a subsetting IF statement, outputting only the final observation for each department containing the accumulated subtotal.
It drops the Last.Department automatic variable from the output dataset.
It sorts the dataset by Department in descending order before writing.
A programmer uses explicit assignment to calculate a running total:
data work.calc;
set work.transactions;
retain Total 0;
Total = Total + Amount;
run;
If Amount is missing (.) on observation 3, what will be the value of Total for observation 3 and all subsequent observations?
Total will ignore observation 3 and retain the total value from observation 2 for all remaining rows.
Total will reset to 0 on observation 3 and continue accumulating subsequent amounts.
Total will become missing (.) on observation 3 and remain missing (.) for all subsequent observations.
SAS will issue a fatal execution error and terminate the DATA step immediately.
What is the initial stored value of a variable specified in a RETAIN statement if no explicit initial value is provided (e.g., retain Count;)?
0
1
0 for numeric variables and blank spaces for character variables
Missing (. for numeric variables, blank for character variables)
Sections you finish are checked off in the contents.