18.4 - Conditionally Executing Do Loops
18.4 - Conditionally Executing Do LoopsAs you now know, the iterative DO loop requires that you specify the number of iterations for the DO loop. However, there are times when you want to execute a DO loop until a condition is reached or while a condition exists, but you don't know how many iterations are needed. That's when the DO UNTIL loop and the DO WHILE loop can help save the day!
In this section, we'll first learn about the DO UNTIL and DO WHILE loops. Then, we'll look at another form of the iterative DO loop that combines features of both conditional and unconditional DO loops.
The DO UNTIL Loop
When you use a DO UNTIL loop, SAS executes the DO loop until the expression you've specified is true. Here's the general form of a DO UNTIL loop:
DO UNTIL (expression);
action statements;
END;
where expression is any valid SAS expression enclosed in parentheses. The key thing to remember is that the expression is not evaluated until the bottom of the loop. Therefore, a DO UNTIL loop always executes at least once. As soon as the expression is determined to be true, the DO loop does not execute again.
Example 18.7
Suppose you want to know how many years it would take to accumulate $50,000 if you deposit $1200 each year into an account that earns 5% interest. The following program uses a DO UNTIL loop to perform the calculation for us:
DATA investment;
DO UNTIL (value >= 50000);
value + 1200;
value + value * 0.05;
year + 1;
OUTPUT;
END;
RUN;
PROC PRINT data = investment NOOBS;
title 'Years until at least $50,000';
RUN;
value | year |
---|---|
1260.00 | 1 |
2583.00 | 2 |
3972.15 | 3 |
5430.76 | 4 |
6962.30 | 5 |
8570.41 | 6 |
10258.93 | 7 |
12031.88 | 8 |
13893.47 | 9 |
15848.14 | 10 |
17900.55 | 11 |
20055.58 | 12 |
22318.36 | 13 |
24694.28 | 14 |
27188.99 | 15 |
29808.44 | 16 |
32558.86 | 17 |
35446.80 | 18 |
38479.14 | 19 |
41663.10 | 20 |
45006.26 | 21 |
48516.57 | 22 |
52202.40 | 23 |
Recall that the expression in the DO UNTIL statement is not evaluated until the bottom of the loop. Therefore, the DO UNTIL loop executes at least once. On the first iteration, the value variable is increased by 1200, or in this case, set to 1200. Then, the value variable is updated by calculating 1200 + 1200*0.05 to get 1260. Then, the year variable is increased by 1, or in this case, set to 1. The first observation, for which year = 1 and value = 1260, is then written to the output data set called investment. Having reached the bottom of the DO UNTIL loop, the expression (value >= 50000) is evaluated to determine if it is true. Since value is just 1260, the expression is not true, and so the DO UNTIL loop is executed once again. The process continues as described until SAS determines that value is at least 50000 and therefore stops executing the DO UNTIL loop.
Launch and run the SAS program, and review the output from the PRINT procedure to convince yourself that it would take 23 years to accumulate at least $50,000.
The DO WHILE Loop
When you use a DO WHILE loop, SAS executes the DO loop while the expression you've specified is true. Here's the general form of a DO WHILE loop:
DO WHILE (expression);
action statements;
END;
where expression is any valid SAS expression enclosed in parentheses. An important difference between the DO UNTIL and DO WHILE statements is that the DO WHILE expression is evaluated at the top of the DO loop. If the expression is false the first time it is evaluated, then the DO loop doesn't even execute once.
Example 18.8
The following program attempts to use a DO WHILE loop to accomplish the same goal as the program above, namely to determine how many years it would take to accumulate \$50,000 if you deposit \$1200 each year into an account that earns 5% interest:
DATA investtwo;
DO WHILE (value >= 50000);
value + 1200;
value + value * 0.05;
year + 1;
OUTPUT;
END;
RUN;
PROC PRINT data = investtwo NOOBS;
title 'Years until at least $50,000';
RUN;
23 PROC PRINT data = investtwo NOOBS;
24 title 'Years until at least $50,000';
25 RUN;
NOTE: No observations in data set WORK.INVESTTWO.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
26 QUIT
Launch and run the SAS program, and review the output from the PRINT procedure to convince yourself that ... OOPS! There is no output! The program fails, because in a DO WHILE loop, the expression, in this case (value >= 50000), is evaluated at the top of the loop. Since value is set to missing before the first iteration of the DATA step, SAS can never enter the DO WHILE loop. Therefore, the code proves to be ineffective. Review the log to convince yourself that the investtwo data set contains no observations because the DO WHILE loop was unable to execute.
Example 18.9
Now, the following program correctly uses a DO WHILE loop to determine how many years it would take to accumulate $50,000 if you deposit $1200 each year into an account that earns 5% interest:
DATA investthree;
value = 0;
DO WHILE (value < 50000);
value + 1200;
value + value * 0.05;
year + 1;
OUTPUT;
END;
RUN;
PROC PRINT data = investthree NOOBS;
title 'Years until at least $50,000';
RUN;
value | year |
---|---|
1260.00 | 1 |
2583.00 | 2 |
3972.15 | 3 |
5430.76 | 4 |
6962.30 | 5 |
8570.41 | 6 |
10258.93 | 7 |
12031.88 | 8 |
13893.47 | 9 |
15848.14 | 10 |
17900.55 | 11 |
20055.58 | 12 |
22318.36 | 13 |
24694.28 | 14 |
27188.99 | 15 |
29808.44 | 16 |
32558.86 | 17 |
35446.80 | 18 |
38479.14 | 19 |
41663.10 | 20 |
45006.26 | 21 |
48516.57 | 22 |
52202.40 | 23 |
Note that there are just three differences between this program and that of the successful program in Example 18.7 that uses the DO UNTIL loop: i) The value variable is initialized to 0; ii) UNTIL has been changed to WHILE; and iii) the expression to be checked is now (value < 50000). Because value is set to 0 and is therefore less than 50000 at the outset, SAS can now enter the DO WHILE loop to perform our desired calculations.
The calculations proceed as before. First, the value variable is updated to by calculating 0 + 1200, to get 1200. Then, the value variable is updated by calculating 1200 + 1200*0.05 to get 1260. Then, the year variable is increased by 1, or in this case, set to 1. The first observation, for which year = 1 and value = 1260, is then written to the output data set called investthree. SAS then returns to the top of the DO WHILE loop, to determine if the expression (value < 50000) is true. Since value is just 1260, the expression is true, and so the DO WHILE loop executes once again. The process continues as described until SAS determines that value is at least 50000 and therefore stops executing the DO WHILE loop.
Launch and run the SAS program, and review the output from the PRINT procedure to convince yourself that this program also determines that it would take 23 years to accumulate at least $50,000.
Using Conditional Clauses in an Iterative DO Loop
You have now seen how the DO WHILE and DO UNTIL loops enable you to execute statements repeatedly, but conditionally so. You have also seen how the iterative DO loop enables you to execute statements a set number of times unconditionally. Now, we'll put the two together to create a form of the iterative DO loop that executes DO loops conditionally as well as unconditionally.
Example 18.10
Suppose again that you want to know how many years it would take to accumulate $50,000 if you deposit $1200 each year into an account that earns 5% interest. But this time, suppose you also want to limit the number of years that you invest to 15 years. The following program uses a conditional iterative DO loop to accumulate our investment until we reach 15 years or until the value of our investment exceeds 50,000, whichever comes first:
DATA investfour (drop = i);
DO i = 1 to 15 UNTIL (value >= 50000);
value + 1200;
value + value * 0.05;
year + 1;
OUTPUT;
END;
RUN;
PROC PRINT data = investfour NOOBS;
title 'Value of Investment';
RUN;;
value | year |
---|---|
1260.00 | 1 |
2583.00 | 2 |
3972.15 | 3 |
5430.76 | 4 |
6962.30 | 5 |
8570.41 | 6 |
10258.93 | 7 |
12031.88 | 8 |
13893.47 | 9 |
15848.14 | 10 |
17900.55 | 11 |
20055.58 | 12 |
22318.36 | 13 |
24694.28 | 14 |
27188.99 | 15 |
Note that there are just two differences between this program and that of the program in Example 18.7 that uses the DO UNTIL loop: i) The iteration i = 1 to 15 has been inserted into the DO UNTIL statement; and ii) because the index variable i is created for the DO loop, it is dropped before writing the contents from the program data vector to the output data set investfour.
Launch and run the SAS program, and review the output from the PRINT procedure to convince yourself that, in this case, 15 years comes first. That is, the portion of the DO statement that tells SAS to stop executing the DO loop is the iterative i = 1 to 15 part.
Example 18.11
Suppose this time that you want to know how many years it would take to accumulate $50,000 if you deposit $3600 each year into an account that earns 5% interest. Suppose again that you want to limit the number of years that you invest to 15 years. The following program uses a conditional iterative DO loop to accumulate our investment until we reach 15 years or until the value of our investment exceeds 50,000, whichever comes first:
DATA investfive (drop = i);
DO i = 1 to 15 UNTIL (value >= 50000);
value + 3600;
value + value * 0.05;
year + 1;
OUTPUT;
END;
RUN;
PROC PRINT data = investfive NOOBS;
title 'Value of Investment';
RUN;
value | year |
---|---|
3780.00 | 1 |
7749.00 | 2 |
11916.45 | 3 |
16292.27 | 4 |
20886.89 | 5 |
25711.23 | 6 |
30776.79 | 7 |
36095.63 | 8 |
41680.41 | 9 |
47544.43 | 10 |
53701.66 | 11 |
There is just one difference between this program and that of the previous program. The amount value has been changed from 1200 to 3600. Launch and run the SAS program, and review the output from the PRINT procedure to convince yourself that, this time, the $50,000 comes first. That is, the portion of the DO statement that tells SAS to stop executing the DO loop is the conditional (value >= 50000) part.
The two examples of using conditional clauses with an iterative DO loop that we looked at involved using a DO UNTIL loop. We alternatively could have used a DO WHILE loop. The main thing to keep in mind is that, as before, the UNTIL expression is evaluated at the bottom of the DO loop, so the DO loop always executes at least once. The WHILE expression is evaluated before the execution of the DO loop. So, if the condition is not true, the DO loop never executes.