Study guide

4.5 Processing Data Iteratively with DO Loops

SAS Certified Specialist: Base Programming Using SAS 9.4 A00-231

Track your progress as you read

Finished sections get a check mark.

1 Chapter 1: SAS Base Programming Exam Overview

1.1 A00-231 Exam Format, Scoring & Test-Day Logistics 1.2 Official Content Areas, Weights & Study Plan

2 Chapter 2: Accessing & Creating SAS Data Structures

2.1 SAS Environment, Syntax Rules, & Data Step Basics 2.2 SAS Data Libraries & the LIBNAME Statement 2.3 Investigating Libraries with PROC CONTENTS & PROC DATASETS 2.4 Importing Delimited & Excel Data with PROC IMPORT 2.5 Raw Data Ingestion with INFILE and INPUT Statements

3 Chapter 3: Managing & Combining SAS Data Sets

3.1 Reading SAS Data Sets with the SET Statement 3.2 Combining Data Sets: Concatenating & Interleaving 3.3 Match-Merging with BY Statements & FIRST./LAST. Processing 3.4 Controlling Data Output & Variable Selection (KEEP, DROP, RENAME, OBS=)

4 Chapter 4: Data Transformation & Conditional Logic

4.1 Creating & Modifying Variables with Assignment Statements 4.2 Modifying Variable Attributes with LENGTH, LABEL, FORMAT & RENAME= 4.3 Conditional Processing: IF-THEN/ELSE Statements & WHERE Subsetting 4.4 Accumulating Totals & Subtotals (RETAIN & Sum Statement) 4.5 Processing Data Iteratively with DO Loops

5 Chapter 5: SAS Functions & Data Type Conversions

5.1 Character Functions for String Manipulation 5.2 Numeric & Mathematical Functions 5.3 Working with SAS Dates, Times, & Intervals 5.4 Reading & Displaying Dates with Informats and Formats 5.5 Explicit & Implicit Data Type Conversions (INPUT & PUT)

6 Chapter 6: Restructuring Data & Program Maintenance

6.1 SAS Array Processing for Multi-Variable Transformations 6.2 Sorting Data Sets with PROC SORT 6.3 Restructuring Data Sets with PROC TRANSPOSE 6.4 Creating & Applying Custom Formats with PROC FORMAT 6.5 Simplifying Programs with Macro Variables (%LET)

7 Chapter 7: Error Handling & Debugging SAS Programs

7.1 SAS Log Analysis & Diagnostic Messages 7.2 Syntax vs. Logic Errors & Phasing 7.3 Debugging Techniques with _ERROR_, _N_, & PUT Statements 7.4 Identifying Logic Errors with the PUTLOG Statement 7.5 Handling Missing Values & Preventing Calculation Propagations

8 Chapter 8: Summary & Detail Data Reporting

8.1 Detail Reporting with PROC PRINT 8.2 Descriptive Statistics with PROC MEANS & PROC SUMMARY 8.3 Frequency & Categorical Analysis with PROC FREQ 8.4 Screening Extreme & Missing Values with PROC UNIVARIATE 8.5 Custom Tabular Reports with PROC REPORT & PROC TABULATE

9 Chapter 9: ODS Output Delivery & Data Export

9.1 Output Delivery System (ODS) Architecture Basics 9.2 Generating PDF, HTML, & RTF Output Destinations 9.3 Exporting Reports to Excel with ODS EXCEL & XLSX 9.4 Generating CSV, PowerPoint & Other ODS Destinations 9.5 Customizing ODS Titles, Footnotes, & Global Options 9.6 Exporting SAS Data Sets with PROC EXPORT & the XLSX Engine

4.5 Processing Data Iteratively with DO Loops

Key Takeaways Explain This Topic AI

DO loops exist to eliminate redundant code and perform repetitive calculations: twelve near-identical assignment statements collapse into one indexed loop that scales when columns are added.

An iterative DO loop executes a block of SAS statements repeatedly as an index variable increments from a specified start value to a stop value by a defined increment.

Upon exiting an iterative DO loop, the index variable retains a value equal to the stop value PLUS the increment value (e.g., DO i=1 TO 10; leaves i=11 after loop exit).

A DO WHILE (condition) loop evaluates its expression BEFORE executing the loop body (pre-test); if the condition evaluates to false on entry, the loop body executes zero times.

A DO UNTIL (condition) loop evaluates its expression AFTER executing the loop body (post-test); the loop body ALWAYS executes at least once regardless of initial condition state.

Last updated: August 2026

4.5 Processing Data Iteratively with DO Loops

Quick Answer: DO loops allow SAS to execute a block of code repetitively. An iterative DO loop uses an index variable that increments from a start value to a stop value. A DO WHILE loop repeats while a condition remains true (evaluating before each execution). A DO UNTIL loop repeats until a condition becomes true (evaluating after each execution, guaranteeing at least one execution).

Iterative DO Loops Mechanics

An iterative DO loop executes statements a specified number of times using an index variable.

  • Syntax DO index-variable = start TO stop <BY increment>;
  • /* SAS statements to execute repeatedly */
  • END;

index-variable : A numeric variable created in the PDV that tracks iteration count.

start : Initial value of the index variable.

stop : Target boundary value.

  • BY increment : Optional increment step size (default is 1 ). data work.table_of_squares;
  • do i = 1 to 5;
  • Square = i ** 2;
  • end;
  • run;
  • CRITICAL EXAM CONCEPT: Index Variable Value Upon Exit

One of the most frequently tested questions on the SAS Base Specialist exam asks for the value of the index variable after an iterative DO loop finishes.

Let me trace do i = 1 to 5; step-by-step:

Iteration 1 : i is set to 1 . 1 <= 5 is true. Square = 1 . END increments i to 2 .

Iteration 2 : i is 2 . 2 <= 5 is true. Square = 4 . END increments i to 3 .

Iteration 3 : i is 3 . 3 <= 5 is true. Square = 9 . END increments i to 4 .

Iteration 4 : i is 4 . 4 <= 5 is true. Square = 16 . END increments i to 5 .

Iteration 5 : i is 5 . 5 <= 5 is true. Square = 25 . END increments i to 6 .

Loop Evaluation : SAS checks i <= 5 ( 6 <= 5 ). Condition is FALSE . Loop terminates!

Golden Rule: When an iterative DO loop terminates normally, the index variable's stored value in the PDV is equal to stop + increment (e.g., 5 + 1 = 6 ).

Eliminating Redundant Code and Repetitive Calculations

The content guide states the practical purpose of iterative loops explicitly: use DO loops to eliminate redundant code and to perform repetitive calculations . Any time the same statement is written more than twice with only an index changing, a DO loop is the intended replacement. /* REDUNDANT: twelve near-identical statements, twelve chances to typo */

  • data work.monthly_adjusted;
  • set work.monthly_raw;
  • Mon1 = Mon1 * 1.03;
  • Mon2 = Mon2 * 1.03;
  • Mon3 = Mon3 * 1.03;
  • /* ... nine more lines ... */
  • Mon12 = Mon12 * 1.03;
  • run;
  • /* CONCISE: one loop, one rate to change, no chance of a skipped month */
  • data work.monthly_adjusted;
  • set work.monthly_raw;
  • array mon{12} Mon1-Mon12;
  • do i = 1 to 12;
  • mon{i} = mon{i} * 1.03;
  • end;
  • drop i;
  • run;

The second use is the repetitive calculation : generating a series of values that do not exist in the input at all. /* Ten-year projection generated from a single input row */

  • data work.amortisation;
  • Principal = 250000;
  • Rate = 0.055;
  • do Year = 1 to 10;
  • Interest = Principal * Rate;
  • Principal = Principal - 12000 + Interest;
  • output; /* one row per projected year */
  • end;
  • format Principal Interest dollar12.2;
  • run;
  • Benefit Why it matters on the exam
  • Fewer lines to mistype Syntax errors on a performance-based exam cost time you cannot recover
  • One place to change a constant A rate written twelve times will eventually disagree with itself
  • Scales with the data do i = 1 to dim(mon); adapts automatically when a column is added

Generates rows absent from the input The only way to build projections, schedules, and simulations in a DATA step

Explicit OUTPUT Statements Inside DO Loops

By default, a DATA step writes an observation to the output dataset only once per DATA step iteration (when reaching the RUN; statement). Placing an explicit OUTPUT; statement inside a DO loop alters this behavior completely.

  • Generating Multiple Observations per Data Step Iteration data work.investment_growth;
  • Capital = 10000;
  • Rate = 0.05;
  • do Year = 1 to 10;
  • Capital = Capital * (1 + Rate);
  • output; /* Writes a row FOR EVERY YEAR iteration of the loop! */
  • end;
  • run;

In work.investment_growth , the explicit OUTPUT; statement inside the loop outputs 10 observations (one for each year). Furthermore, placing an explicit OUTPUT statement anywhere in a DATA step suppresses the automatic output at the bottom of the DATA step.

Conditional Loops: DO WHILE vs. DO UNTIL

When the number of required iterations is unknown in advance (e.g., calculating how many years until an investment doubles), use conditional DO loops.

  • DO WHILE Loop (Pre-Test Loop)
  • Evaluates the condition BEFORE executing the loop body. DO WHILE (expression);
  • /* statements */
  • END;

Executes as long as expression is TRUE .

  • If expression is FALSE on entry, the loop body executes 0 times . data work.while_example;
  • Capital = 100000; /* Capital is ALREADY >= 50000 */
  • Years = 0;
  • /* Evaluates (Capital < 50000) BEFORE entry -> FALSE! */
  • do while (Capital < 50000);
  • Years + 1;
  • Capital = Capital * 1.05;
  • end;
  • run;
  • /* Result: Years = 0, Capital = 100000 (Loop executed 0 times) */
  • DO UNTIL Loop (Post-Test Loop)
  • Evaluates the condition AFTER executing the loop body. DO UNTIL (expression);
  • /* statements */
  • END;

Executes as long as expression is FALSE , terminating when it becomes TRUE .

  • Because the test occurs at END , the loop body ALWAYS executes at least ONCE . data work.until_example;
  • Capital = 100000; /* Capital is ALREADY >= 50000 */
  • Years = 0;
  • /* Executes body FIRST, then evaluates (Capital >= 50000) -> TRUE! Terminates loop. */
  • do until (Capital >= 50000);
  • Years + 1;
  • Capital = Capital * 1.05;
  • end;
  • run;
  • /* Result: Years = 1, Capital = 105000 (Loop executed 1 time!) */
  • Nested DO Loops

A DO loop may contain another DO loop. Each nested loop needs its own index variable and its own END; statement, and the inner loop runs to completion on every single iteration of the outer loop. Total iterations equal the product of the two ranges. /* Build a 3-region x 4-quarter forecasting grid = 12 observations */

  • data work.forecast_grid;
  • set work.base_rates; /* one input row: BaseAmount */
  • do RegionNum = 1 to 3; /* OUTER loop: 3 iterations */
  • do Quarter = 1 to 4; /* INNER loop: 4 per region */
  • Projected = BaseAmount * (1 + 0.02 * Quarter) * RegionNum;
  • output; /* 3 x 4 = 12 rows written */
  • end; /* closes the INNER loop */
  • end; /* closes the OUTER loop */
  • run;
  • Rules and Traps for Nested Loops

One END; per DO — an unmatched END makes SAS swallow the rest of the DATA step and usually produces a confusing ERROR: There is an extra END statement or an infinite construct.

Distinct index variables — reusing i for both loops causes the inner loop to overwrite the outer counter, so the outer loop never advances correctly.

Where OUTPUT; sits determines the row count — inside the inner loop you get 12 rows; between end; and end; you get 3 rows; after both end; statements you get 1 row.

Index values after exit — each index still ends at stop + increment ( RegionNum = 4 , Quarter = 5 ) unless you drop them.

Comparison: DO Loop Variants

  • Feature Iterative DO DO WHILE DO UNTIL
  • Test Timing Before each iteration Pre-test (Before loop body) Post-test (After loop body)
  • Termination Condition Index exceeds stop value Expression becomes FALSE Expression becomes TRUE
  • Minimum Iterations 0 (if start > stop) 0 iterations 1 iteration (Guaranteed)
  • Index Variable Managed automatically Managed manually inside loop Managed manually inside loop
  • Common Use Case Fixed counts, arrays Condition monitoring (0+ runs) Condition monitoring (1+ runs)
  • Combining Iterative and Conditional Clauses

You can combine iterative index processing with WHILE or UNTIL clauses to set safety limits and prevent infinite loops: data work.safe_projection;

Capital = 10000;

  • /* Runs for a maximum of 30 years OR UNTIL Capital reaches 50,000 */
  • do Year = 1 to 30 until (Capital >= 50000);
  • Capital = Capital * 1.07;
  • end;
  • run;