Week 1 Coding Lecture 2: Vectors
Suppose that you are responsible for calculating the total grades for a class. As an example, suppose that the class has homework assignments worth a total of 190 points, tests worth a total of 200 points and quizzes worth a total of 50 points. To calculate a student's final grade, you need to add up their homework, test and quiz scores and divide by the total number of possible points (440). For example, suppose we had four students with the following grades:
- Name | Homework | Quizzes | Tests
- Alice | 170 | 45 | 160
- Bob | 163 | 40 | 195
- Carol | 188 | 50 | 138
- Dan | 150 | 36 | 172
Here is one way we could calculate all of the students' grades in MATLAB: First, we enter all of the data into MATLAB variables.
Next, we use the formula final = (hw + quiz + test) / 440 to calculate each student's final grade.
final1 = (hw1 + quiz1 + test1) / total_possible
final2 = (hw2 + quiz2 + test2) / total_possible
final3 = (hw3 + quiz3 + test3) / total_possible
final4 = (hw4 + quiz4 + test4) / total_possible
As you have probably noticed, this is not a very good method. For one thing, this involved a lot of typing (and imagine how much worse it would be with hundreds of students instead of four!). In addition, we had to make many variables with similar names like hw1, hw2, hw3 and hw4. It would be very easy to make a mistake with one of these variable names somewhere in the code, and it would take a lot of time to find and fix the problem. Another issue that might not seem as obvious is that this code is difficult to change. For example, if we decided to change the formula for calculating final grades then we would have to make identical changes to our code in four different places. This creates more unecessary typing and more opportunities for error.
A much better solution is to group grades together under just a few variable names. For example, we could put all the homework grades together in one variable, all the quiz grades together in another, etc. We can do this with the code:
test = [160, 195 138, 172]
These variables are called vectors (or more specifically, row vectors). For now, you should think of them as lists of numbers, but we will see soon that they have more in common with mathematical vectors than simple lists.
(This is a place where the nomenclature in MATLAB is quite different from other languages like python. In particular, a "vector" in MATLAB is roughly equivalent to a "list" or "array" or "one dimensional array" in python.)
You construct a row vector by surrounding the entire list with square brackets and separating the entries with either spaces or commas. As you can see above, it doesn't matter if you choose spaces, commas, or even if you mix and match. That said, I recommend that you choose one and stick to it. I will almost always use spaces in these notes. If you look in the workspace, you can see the vectors hw, quiz and test. They look similar to other variables, but if you hover over them you will see 1x4 double instead of 1x1 double. This indicates that they are row vectors with four entries. It's also worth noting that you can double click on a variable in the workspace to see it in a scrollable window. That can be useful when the vector is too long to display in the workspace.
Almost any operation that makes sense when applied to one number also make sense when applied to a vector. MATLAB just does the operation to every number in the vector. For example,
test_divided_by_ten = test / 10
quiz_plus_five = quiz + 5
However, most operations that involve two vectors (like hw * test) don't do what you would expect (unless you are a physicist or mathematician). The two notable exceptions are addition and subtraction. If you add or subtract two vectors (of exactly the same size/shape) then MATLAB just add/subtracts each corresponding element. For example:
However, if you try to multiply two vectors (like hw * test) MATLAB will throw an error. The same thing happens if you try to raise a vector to a power (like hw^2). If you try to divide two vectors, MATLAB may or may not give you an answer, but it is almost certainly not the answer you wanted. We will talk extensively about what this division operator does later in the class.
If you want multiply/divide each number in a vector by the corresponding number in another vector, you need to add a dot (.) to the operator. For example,
hw_dot_times_test = hw .* test
test_dot_divide_quiz = test ./ quiz
Note that these only work if the two vectors being multiplied or divided are exactly the same length. For instance, if you try to run this:
x = [1 2 3 4];
y = [5 6 7 8 9];
x .* y
in the command window, you will see the error "Matrix dimensions must agree".
Remember that our goal is to calculate the final scores for each student. We can do this with
final = (hw + quiz + test) / total_possible
There is a lot of extraneous example code in between, but if you look back you'll see that we reduced 17 lines of code to 5. (In fact, this code also runs faster than the previous version. It is both more convenient and more efficient to keep all of your data in vectors.)
While we cleaned up our code quite a bit by using vectors, it does seem like we might have lost something important. Suppose that Carol comes to you and asks for her grade. Before, you could simply type
but that won't work here. (Depending on the order in which you ran these sections, you may or may not see an error here. We defined the variable final3 in the first section, and so if you have already run that section then this code will work fine. However, if you have only run this section then final3 is an undefined variable.) We could of course just type
to display all of the grades and tell Carol that hers is the third number, but we don't want to share everyone else's grade with one student. Fortunately, MATLAB has simple shortcuts to access individual entries in a vector. If we want the third entry in final, we can just type
Rows vs Columns
As we have seen, you can create a row vector by listing the entries (separated by spaces or commas) and surrounding the entire list with square brackets.
Since I have taken care to call these "row vectors", you can probably guess that there are also "column vectors". You define a column vector in the same way as a row vector, except you separate the entries with a semicolon instead of a comma/space. For example:
(Note that the white space after each semicolon is optional. That is, you could also write a = [1;2;3;4;5], but I highly recommend that you use the spaces to make things more readable.)
We will see later that there is an important mathematical distinction between row and column vectors. (You probably already know this if you've taken a linear algebra course.) However, if you are just using vectors to hold lists of data, then it doesn't really matter if you choose to use a row or a column.
(This is another place where MATLAB is different from other languages like python. In most languages, there is a type of variable called a vector or list or array that is essentially just a list of numbers. Such types have a length but not a shape, and so there is no distinction between rows and columns. Languages like python also have two-dimensional arrays, which can have multiple rows and columns. MATLAB's row vectors and column vectors are special cases of these 2D arrays. MATLAB was designed with linear algebra and matrices in mind, and so every variable in MATLAB is actually a 2D array. That is why you see "1x1 double" when you define a single number. The number is actually stored in a 2D array with one row and one column.)
Although you can often use rows or columns interchangably, it is important to be consistent. This is because the basic arithmetic operations that we've seen before only work (or more accurately, only work as expected) when you combine vectors of exactly the same size and shape. For example,
both add together corresponding elements of the two vectors. Notice that we get essentially the same answer whether we use rows or columns. However,
does not do at all what one would expect. (Can you see how MATLAB came up with this answer?) Similarly, the .* and ./ operators only work as expected when both vectors are the same size and shape. Notice the difference between
For now, you can just choose to use row vectors or column vectors and then stick to the choice consistently.
If you want to switch a vector from a row to a column or vice versa, you can use the transpose operator. In mathematical notation, the transpose is denoted by a superscript T. For instance, . In MATLAB, you can use the apostrophe ' to transpose a vector.
(Technically, ' is the conjugate transpose. This means that if your vector has complex numbers in it, then the sign of any imaginary part will switch when you use the ' operator. We will very rarely use complex numbers in this class, and when we do we will probably want the conjugate transpose anyways. If you don't want this behavior, you can use the operator .' instead.)
Accessing and modifying vector entries
We have already seen how to access individual entries from a vector. The syntax is name_of_vector(number_of_entry). For instance, if we have the vectors
we can get the second entry of each vector with
Notice that this syntax is the same for row and column vectors. It is important to remember that MATLAB always counts entries with whole numbers and it always starts counting at 1. This can be confusing if you are used to zero-indexed languages like python.
The following are therefore acceptable code:
but if you try to execute the following in the command window you will get an error:
Likewise, you cannot try to access an entry that is past the end of the array. For instance, the code
will cause an error if you try to run it in the command window because y does not have five entries.
There is also a shortcut for counting from the end of a vector. If you want the last entry of y, you can use
Likewise, the second to last entry is
and the third to last entry is
Note that end is a reserved word in MATLAB. You can't use it as a variable name, and if you try to use it outside of this vector syntax you will probably get an error.
You should think of the vector access syntax as being a variable name. x(3) is the name of the 3rd entry of x. You can use this syntax anywhere a variable name would be appropriate. In particular, you can use it in calculations like
and you can use it in variable assignment like
Even more importantly, you can also use this syntax on the left side of the = operator to modify the contents of a vector. For example,
overwrites the second entry of x with a value of 10.
Just like how variable names work slightly differently on the left and right side of the = operator, vector access syntax also has slightly different behavior. In particular, you cannot use an entry past the end of a vector on the right side of an = operator, but you can use it on the left side. That is, the code
will cause an error if you try to run it in the command window, but the code
runs successfully. As you can see, if you try to define an entry past the end of a vector, MATLAB extends the vector to the appropriate size and fills in any extra entries with zeros.
The colon operator
It is very common to need vectors of evenly spaced numbers. MATLAB has a convenient shortcut for this purpose: The colon operator. It has a few modes of use, but the simplest is to make a vector of numbers starting from some starting number and going up by 1 until they reach some final number. The syntax is start:stop. For example,
More generally, you might want the entries to change by something other than 1. You can specify a different step size with the syntax start:step:stop. For instance,
As you can see, the first entry of the vector is the value start, and then MATLAB adds step to the value over and over again until it reaches stop. It's worth noting that none of the entries in your vector will ever go past the value of stop. To see why this matters, consider the vector
The values start at 1 and increase by 2 each time. MATLAB always starts your vector just before it overshoots stop, so the final element in x is 9 and not 11.
It is also worth noting that the colon operator always produces a row vector. If you want a column vector instead, you can use the transpose:
(The parentheses are important here. What happens if you don't use them?)
You can use the colon operator to access more than one entry from a vector. For example, if we have the vector
then we can access the second, third and fourth entries with the syntax
This is because 2:4 is just the vector [2 3 4], and so MATLAB interprets this as the second, third and fourth entries. Similarly, if we want the first, third, fifth and seventh entries we can use
We can also use the end keyword with colon operators as a shortcut for the last entry in the vector. For example,
gives all the entries of x,
gives all the even entries of x, and
gives the last three entries in reverse order.
You can also use the colon syntax to modify multiple entries of a vector. There are two different ways of doing this. If you want to make every entry the same thing, you can use vector_name(start:step:stop) = value. For example,
sets alll the odd entries to zero. If you want some of the entries to be different, you have to use vector_name(start:step:stop) = vector_of_values, where vector_of_values is the same size as start:step:stop. For instance,
does not because the vector on the right only has three elements, but we are trying to change five elements of x.
There are a few things worth remembering about this syntax:
- If any number in your colon operator isn't a valid index, then this will cause an error. For instance, x(1:0.5:2) will cause an error because x(1.5) is not valid. Likewise, x(0:2) won't work because x(0) isn't valid.
- You can modify entries past the end of a vector, but you can't access them. This means that if x has 9 entries then y = x(1:100) will cause an error, but x(1:100) = 3 will not. In the latter case, MATLAB just extends x to the appropriate length.
- The end syntax is only legal when accessing entries of a vector. If you try to use it in a different context, you will get an error. For instance, x = 1:end will not work.
This syntax is actually a special example of a more general method. You can access or modify multiple entries from a vector with the syntax vector_name(vector_of_indices). So
accesses the third, first, sixth and ninth entries of x. We won't use this last method very often in the class, but it's worth playing around with a little to get comfortable with.