Lecture 5

Chapter 5 - Loop Statements and Vectorizing Code

Synopsis
In Lecture 4, we learned how to use conditional statements to selectively execute pieces of code. In this class, we will discuss the contents of Chapter 5: Loop Statements and Vectorizing Code, and learn how to repeatedly execute lines of code to perform different tasks. The topics that will be covered include for loops, nested for loops, while loops, and vectorizing.


Daily Quiz

Quiz 7


for Loops

We now know how to selectively execute pieces of code using conditional statements. This lets us perform different tasks depending on the values in our variables. But what do we do if we want to repeat a section of code? Well, we could always copy and paste a line of code multiple times, but this would be tedious and make our code unreadable. Fortunately, there are loop statements that will allow us to repeatedly execute lines of code under various conditions. There are two types of loop statements in MATALB: for and while. for loops are also called counted loops because they repeat an action a defined number of times. If we wanted to print a character (e.g. $) five times, we would use a for loop because we know the number of times that we want the character to be printed. Let's begin by looking at the form of a for loop.

1
2
3
for index = range
    action
end

Just like if statements, for loops are initiated by a reserved word (for), contain some action, and terminate with end. Unlike if statements, we have a strange looking assignment operation index = range instead of a conditional statement. As we mentioned, for loops are used when we know the number of times that we would like the action to be executed. That number is defined by the vector range. Each element of the range vector is iteratively assigned to the loop variable index. On the first iteration of the for loop, index contains the first element of range. On the second iteration of the for loop, index contains the second element of range. And so on. If we would like the for loop to execute five times, we define range as a vector of numbers from 1 to 5.

1
2
3
4
%print a message 5 times
for i = 1:5
    disp('print me')
end
print me
print me
print me
print me
print me

As you recall, we can create a vector containing values from 1 to 5 by using the colon operator. Traditionally, the elements of range are assigned to loop variables with single letter names starting with i. It's important to remember that i and j are constants in MATLAB, and using them as loop variables will overwrite their value of sqrt(-1). In the above code, we are simply printing the same statement five times, and we have not used the looping variable. To more clearly illustrate how i iteratively contains each element of the vector defined by 1:5, we can change the print statement to display the value held by i.

1
2
3
4
%print values in i
for i = 1:5
    disp(i)
end
1
2
3
4
5

Printing values of i is not the most useful way to use for loops. Let's take a look at a more practical example.

Batch Processing

MATLAB is often used to analyze data in a file, and we learned how to load data in Lab 2. But what if we wanted to perform the same analysis on multiple files within a directory? Let's assume that we have a vector containing the path to each file that needs to be analyzed (called filepaths), and we have a separate matlab function called myanalysis that performs our calculations. Our goal is to execute myanalsis for all of the files in filepaths. We can use a for loop to access each element of filepath and call the function myanalysis. Let's see how this is done.

1
2
3
4
5
%perform myanalsis on each file in filepaths
for i = 1:length(filepaths)
    data = load(filepaths(i));
    myanalysis(data);
end

There is a lot going on in these few lines, so we will discuss each section. First, we are defining our range to be 1:length(filepaths) because we would like the for loop to execute for each file in filepaths, but we don't necessarily know how many files the vector filepaths contains. 1:length(filepaths) creates a sequence of numbers from 1 to the number of elements of filepaths.

Now that we have the for loop defined, let's examine the action. Line 3 of our code imports the i th element of filepaths by indexing the vector filepaths using the loop variable i. In line 4, we are calling the function myanalsis and passing the data variable. This loop will iterate for each file contained in filepaths and perform myanalysis.

But what if we want to store a value returned by myanalysis? We could store the value in a variable using result = myanalysis(date); however, result would be overwritten after each iteration of the for loop. The most common way to store multiple results from a for loop is in a vector or matrix where each result is stored as a different element. The best way to do this in MATLAB is to preallocate the vector before the for loop and replace elements by indexing. Let's modify our code to store results from myanalysis.

1
2
3
4
5
6
7
8
%preallocate vector
results = zeros(1,length(filepaths));

%perform myanalsis on each file in filepaths
for i = 1:length(filepaths)
    data = load(filepaths(i));
    results(i) = myanalysis(data);
end

As you can see, we've preallocated results as a vector of zeros. Then, we replace each element of results with the value returned by myanalysis. In the end, the i th element of results will contain the returned value for the i th file in filepaths.

Nested for Loops

Similar to if statements, the action of a for loop can be another for loop. When might we use this? Let's suppose each file in filepaths contains two lines of data, and we would like to perform myanalyis on each line separately. We can use one for loop to iterate through the files, and another for loop to iterate through the lines of each file. Since we are now receiving two values for each file, our results variable should be preallocated as a matrix.

1
2
3
4
5
6
7
8
9
10
11
12
%preallocate matrix
results = zeros(2,length(filepaths));

%iterate through each file in filepaths
for i = 1:length(filepaths)
    data = load(filepaths(i));

    %iterate through each line of data
    for j = 1:2
        results(j,i) = myanalsis(data(j,:))
    end
end

As we can see, our code uses i as the loop variable to iterate through filepaths and j as the loop variable to iterate through the two lines of data. Traditionally, the first loop is called the outer loop and the second loop is called the inner loop. Here we have one inner loop, but we can have several inner loops depending on the number of items that need to be iterated.

while Loops

Sometimes we don't know how many times to execute a section of code, but we would like the code to run as long as some condition is satisfied. In these situations, the while loop is our go-to control statement. while loops are similar to if statements in that they execute an action when a condition is true. Unlike if statements, while loops will continue to execute for as long as the condition remains true. Let's look at the format of a while loop.

1
2
3
while condition
    action
end

Suppose that we want the user to enter a value between 0 and 9, inclusive. We could use an if statement to check that the user entered a value in the correct range, but this code would only execute once. What we really want is to continually prompt the user for input until they enter a value in the correct range. Since we don't know how many times this could be, we cannot use a for loop. This is a perfect scenario for using while loops. Let's look at the code.

1
2
3
4
5
6
7
8
%prompt user for value
ui = input('Enter a number between 0 and 9 (inclusive): ');

%if value is out of range, then prompt again
while ui < 0 || ui > 9
    disp('You did not enter a valid number')
    ui = input('Enter a number between 0 and 9 (inclusive): ');
end

In line 2, we ask the user to input a number. We then use a relational expression in line 5 to check if the value is less than 0 or greater than 9. If so, we prompt the user again for input. Before exiting the while loop, we check again to see if ui is less than 0 or greater than 9. If so, the while loop will begin again. In this way, the loop continues until the user enters a valid number or kills the program with Ctrl-C.

As you can see, while loops are particularly useful when we don't know how many times a section of code needs to be executed. However, we can get ourselves in trouble if we are not careful. Let's remove line 7 from the code above, and analyze the results.

1
2
3
4
5
6
7
%prompt user for value
ui = input('Enter a number between 0 and 9 (inclusive): ');

%if value is out of range, then prompt again
while ui < 0 || ui > 9
    disp('You did not enter a valid number')
end

The code will begin as it did before by asking the user for input. We then check if the input is less than 0 or greater than 9. If so, we inform the user that the value was not in the range. Uh, oh... we've removed the code that asks for another value. In this case, ui still contains the invalid value. Each time the value is checked by the while loop, it returns true and executes line 6. We've just created an infinite loop of print statements, and the program never ends. At this point, our only hope is to kill the program by pressing Ctrl-C or exiting MATLAB. When using loops, we should always be careful not to create conditions that prevents an eventual exit.

Vectorizing

for and while loops have particularly important applications in programming. Unfortunately, overusing these control structures can lead to unnecessarily slow programs. Take, for example, the multiplication of a vector and a scalar. We could easily write a for loop to multiply each element of the vector by the scalar.

1
2
3
4
5
6
7
8
%initialize vector
vect = [1 4 6 2];

%multiply each element by 3
for i = 1:length(vect)
    vect(i) = vect(i) * 3;
end
disp(vect)
     3    12    18     6

As we can see, this code works perfectly. However, MATLAB is specifically designed to work efficiently with vectors and matrices. Many of the operations that would require for loops in lower-level programming languages can be done with matrix operations in MATLAB. The concept of using matrix operations instead of loops is called vectorizing. In fact, we can accomplish scalar multiplication faster and in fewer lines of code by vectorizing.

1
2
3
4
5
%initialize vector
vect = [1 4 6 2];

%multiply each element by 3
disp(vect*3)
     3    12    18     6

Whenever you are considering using a loop in MATLAB, ask yourself if the same task can be accomplished as a matrix operation. If so, you can save yourself some typing and increase the speed of your program by vectorizing the task.


Final Words

We now know how to use selection statements and loop statements to modify the flow of our code. Using these elements, we can create a much wider variety of programs that can dynamically adapt to different inputs. In the next class, we will learn how to use these control statements in creative ways to accomplish difficult tasks.