Return to Archive

SAS Tip of the Month
November 2009

This month I am looking at the DO statement - it its simplest form this specifies a set of statements that are to be done until a matching END statement appears.

There are five basic forms of the DO statement:

  • DO
  • interactive DO
  • DO WHILE
  • DO UNTIL
  • DO OVER

The simple form of the DO statement is:

   DO;
      *More SAS statements;
   END;

This version of the DO statement is more often seen in the selection of statements that are run if a condition is true:

   IF condition THEN DO;
      *More SAS statements;
   END;

Before looking at the interactive way the DO statement is used, I will change things around from what you see in most textbooks and talk about two forms that use expressions to determine when the loops stops - the DO WHILE and DO UNTIL.

The first is the DO WHILE statement that carries out a set of statements while a condition is true - this has the form:

   DO WHILE(expression);
      *More SAS statements;
   END;

The second is the DO UNTIL statement that carries out a set of statements until a condition is true - this has the form:

   DO UNTIL(expression);
      *More SAS statements;
   END;

For the WHILE and UNTIL, the expression (an expression is a trail of operands and/or operators that result in a TRUE or FALSE answer) is evaluated. In the case of a DO WHILE, the expression is evaluated at the top the loop, while in the DO UNTIL form the expression is evaluated at the bottom of the loop. The following code will show its use and the difference between these two forms of the DO:

    1    data _null_;
    2       put 'Example using DO WHILE:';
    3       i=0;
    4       do while(i<5);
    5          put @3 i=;
    6          i+1;
    7       end;
    8
    9       put 'Example using DO UNTIL:';
   10       i=0;
   11      do until(i=5);
   12         put @3 i=;
   13         i+1;
   14      end;
   15   run;

   Example using DO WHILE:
     i=0
     i=1
     i=2
     i=3
     i=4
   Example using DO UNTIL:
     i=0
     i=1
     i=2
     i=3
     i=4

Note that a DO UNTIL loop will always do at least one iteration since it is evaluated at the end of the loop. A word of warning though when using the DO WHERE or DO UNTIL - if the expression is never satisfied then the loop will never stop.

The Interactive DO statement uses a variable for an index value, and the SAS code between the DO and END statements is repeated for each value of the index variable. There are a couple of versions of this which are shown below:

   DO index_variable = start_value TO stop_value;
      *More SAS statements;
   END;

   DO index_variable = start_value TO stop_value BY by_value;
      *More SAS statements;
   END;

Each of these two versions above can be extended with the use of a WHILE or UNTIL as detailed above.

Another version of this is where the values for the INDEX_VARIABLE are specified:

   DO index_variable = value1, value2, valuen;
      *More SAS statements;
   END;

The last form of the DO statement that I will look at here is the DO OVER statement - this will action the statements within the loop for all the elements defined within an array, as the following example shows:

   ARRAY monthval {12} jan feb mar apr may jun jul aug sep oct nov dec;
   DO OVER monthval;
      *More SAS statements;
   END;

Below are some examples of valid DO loops:

   do i=1 to 10;
   do i=1 to 10 by 2;
   do i=0 to 10 by 3 while(x=y);
   do i=1,6,3;
   do i=1 to 10, 15, 20 to 16 by -1;
   do while(i<20);
   do until(i>=20);
   do i='01JAN2009'd to '31DEC2009'd;

To prematurely break out of a DO loop there are two ways of doing this - this is actually very useful to make sure that an infinite loop is not created.

The first way is the use of the LEAVE statement that stops the processing of the DO loop and continues with the next statement following the END of the DO loop. The following demonstrates its use:

   leaving_bonus=0;
   DO i=1 TO years_of_service;
      leaving_bonus+50;
      ** Stop if Leaving Bonus > 500;
      IF leaving_bonus>=500 THEN LEAVE;
   END;

Another way is to use a flag variable - if the flag is 'OFF' then continue, else if 'ON' then stop:

   leaving_bonus=0;
   stopflag=0;  ** Flag variable;
   DO i=1 TO years_of_service WHILE(stopflag=0);
      leaving_bonus+50;
      ** Stop if Leaving Bonus > 500;
      IF leaving_bonus>=500 THEN stopflag=1;
   END;

In both of the methods above, the flow of step will continue to any statements set after the END statement associated with the DO statement.

DO loops of course can be nested, that is have a DO loop within a DO loop - the number of loops within a loop you can write is for all practical purposes unlimited, but it would be very have to leave if you had too many levels! See the following for an example of a nested DO loop:

   DO years=1990 TO 2009;
      DO months=1 TO 12;
         *More SAS statements;
      END;
   END;

I hope the tip for this month has taught you something about the DO statement. As always, I ask you to take the code and try it out for yourself - this is the best way to learn.

See you all in December.

________________________________
Updated November 5, 2009