# MATLAB Vectorization Demystified – Part 2: Matrices and Indexing

“MATLAB Vectorization Demystified”: In this series, I try to explain vectorization operation in MATLAB in details step-by-step through several examples. This is part 2 in which “Matrices and Indexing” are explained.

### Matrix definition

Every variable in MATLAB is an array that can hold many numbers, characters, strings, date and times, and so on. Arrays in MATLAB can be 2 or 3 dimensional or even higher. Note that the word “matrix” typically refers to a 2D array, whereas an “array” can be n-dimensional. Early versions of MATLAB supported only 2D matrices, not n-dimensional arrays. That’s the reason for different operations for matrix and array in MATLAB, as discussed in here.

Let’s start with 2D arrays or matrices in MATLAB. An -by- 2D array can be illustrated as follows: Let’s create a 3-by-3 2D matrix. We can use `magic(n)` function, which returns an -by- matrix constructed from the integers 1 to .

```sampleMatrix1 = magic(3)
```

sampleMatrix1 =
8      1      6
3      5      7
4      9      2

To return the number of rows and columns of a matrix, we can use:

```NoOfRows = size(sampleMatrix1 , 1)
```

NoOfRows =
3

```NoOfCols = size(sampleMatrix1 , 2)
```

NoOfCols =
3

Alternatively, you can obtain the number of rows and columns with a single command:

```[NoOfRows , NoOfCols] = size(sampleMatrix1)
```

NoOfRows =
3
NoOfCols =
3

There are two ways for indexing an array/matrix in MATLAB, which are subscript and linear indexing. Both ways are explained in the following sections.

### Subscript indexing

In this approach, the indices of the rows and columns can be specified for indexing. For instance, if we want to retrieve the element in row 2 and column 3, we can say `arrayName(2,3)`, where `arrayName` is the name of the array in your code. It can be shown graphically as follows: It can be seen that every element has a unique pair of `(row,col)` number that can be used for indexing.

### Linear indexing

We can also refer to the elements of a matrix with a single subscript instead of a pair of `(row,col)` number, i.e., `arrayName(k)` where `arrayName` is the name of the array in your code. In fact, MATLAB stores matrices and arrays not in the shape that they appear when displayed in Command Window as in the figure above, but as a single column of elements. This single column is composed of all of the columns from the matrix, each appended to the last as shown in the figure below: Linear indexing for a 2D array

It can be seen that the elements from top to bottom of the columns from left to right as stacked on top of each other in the linear indexing.

Let’s see the two approaches in action. We want to access the element in 2nd row and 3rd column using both approaches, as shown in the figure below: ```sampleMatrix1(2 , 3)    % subscript indexing
```

ans =
7

```sampleMatrix1(8)    % 2M+2 = 2*3+2 = 8, linear indexing
```

ans =
7

It is obvious that we have reached to the same element. So, it is working 🙂.

MATLAB provides `sub2ind()` and `ind2sub()` functions to allow switching between the two indexing approaches. The first command uses the given pair of `(row,col)` subscripts to calculate the linear subscripts. For instance, let’s find the linear index of `(2,3)` and `(1,3)` elements as shown in the figure below: Converting subscripts to linear indices

```% Matrix size, row indices, column indices
sub2ind(size(sampleMatrix1) , [2 3] , [1 3])
```

ans =
2    9

Alternatively, we can use `ind2sub` command to find the associated row-column subscripts from a given set of linear indices:

```% Matrix size, linear subscripts
[Rows , Cols] = ind2sub(size(sampleMatrix1) , [2 9])
```

Rows =
2    3
Cols =
1    3

For the rest of this course, we use pair `(row,col)` subscript indexing unless otherwise mentioned.

### Nonconsecutive elements multiple elements indexing using another vector

We can use what we learned in the first lesson about vectors to index a matrix/array. However, in the case of subscript indexing, we need to specify the indices for both rows and columns.

Let’s assume that we have a 4-by-8 matrix with random numbers. We are interested to return the odd elements of rows and even elements of columns:

```rng(1,'twister')
% randi() generates uniformly distributed pseudorandom integers
sampleMatrix2 = randi(1000 , 4 , 8)
```

sampleMatrix2 =
418    147    397    205    418    801    877    170
721    93     539    879    559    969    895    879
1      187    420    28     141    314    86     99
303    346    686    671    199    693    40     422

```sampleMatrix2(1:2:end , 2:2:end)
```

ans =
1472    205     801     170
187     28      314     99

From the example above, it is clear that we can use `end` reserved keyword for both rows and columns. `end` keyword in the row position points to the number of rows while `end` in the second position refers to the end of columns. Colon operator `:` is another reserved keyword which returns all the elements of a specific dimension. Let’s say we want to return all rows and every third column of `sampleMatrix2`:

```sampleMatrix2(: , 3:3:end)
```

ans =
397    801
539    969
420    314
686    693

If we are interested in specific rows or columns, we can use new vector to specify the subscripts. Let’s say we want to return 3rd and 4th rows and every third column:

```sampleMatrix2([3 4] , 3:3:end)
```

ans =
420    314
686    693

### Single-colon indexing

When you index into a standard MATLAB array using a single colon `:`, MATLAB returns a column vector which follows the linear subscript rule to retrieve the elements from the matrix:

```sampleMatrix2N = [1 2 3 ; 4 5 6]
```

sampleMatrix2N =
1    2    3
4    5    6

```sampleMatrix2N(:)
```

sampleMatrix2N =
1
4
2
5
3
6

### Logical indexing

Similar to vectors, MATLAB allows logical indexing for matrix/arrays. The principles are the same except that you should implement the logics for both rows and columns.

Let’s say we want to return the row-column subscripts of all the odd elements in `sampleMatrix2`:

```rem(sampleMatrix2 , 2) ~= 0
```

ans =
4 × 8 logical array
0    1    1    1    0    1    1    0
1    1    1    1    1    1    1    1
1    1    0    0    1    0    0    1
1    0    0    1    1    1    0    0

You can see that a logical array is returned with the same number of rows and columns as in `sampleMatrix2`. Where the element of the matrix is odd, the logical array shows 1 and vice versa.

To return the actual numbers:

```% I transposed just for better display
sampleMatrix2(rem(sampleMatrix2 , 2) ~= 0)'
```

ans =
721    1    303    147    93    187    397    539    205    879    671    559    141    199    801    969    693    877    895    879    99

If we are interested in the associated rows and columns indices, we can use `find()` command:

```% I transposed just for better display
find(rem(sampleMatrix2 , 2) ~= 0)'
```

ans =
2    3    4    5    6    7    9    10    13    14    16    18    19    20    21    22    24    25    26    30    31

You can see that what is returned is the linear subscript, not the pair of `(row,col)` subscripts indices. We already learned how to do the conversion, right?:

```[Rows , Cols] = ind2sub(size(sampleMatrix2) , ...
find(rem(sampleMatrix2 , 2) ~= 0));
disp(Rows') , disp(Cols')     % just for better display
```

ans =
2    3    4    1    2    3    1    2    1    2    4    2    3    4    1    2    4    1    2    2    3
1    1    1    2    2    2    3    3    4    4    4    5    5    5    6    6    6    7    7    8    8

Let’s say we need the row numbers in which the elements are divisible by 2 and 5:

```% I transposed just for better display
sampleMatrix2(rem(sampleMatrix2 , 2) == 0 & ...
rem(sampleMatrix2 , 5) == 0)'
```

ans =
420    40    170

What really happens if we don’t want to use logical indexing? How does the code look like to run the above operation? Well, we definitely need to run through every element and check with the given condition:

```% placeholder to save the results
results = [];
% for large matrices, pre-allocation of results
% might cost higher computation time
% index to count the elements in results
Ind = 1;
% to loop through all the columns
for i = 1:size(sampleMatrix2 , 2)
% to loop through all the rows
for j = 1:size(sampleMatrix2 , 1)
% checking the condition
if rem(sampleMatrix2(j , i) , 2) == 0 && ...
rem(sampleMatrix2(j , i) , 5) == 0
results(Ind) = sampleMatrix2(j , i);
Ind = Ind + 1;
end
end
end
results
```

results =
420    40    170

It yields the same results, but with the cost of more complicated, longer, and uglier code and probably slower for large matrices.

### Assigning to elements outside array bounds

When you assign to elements outside the bounds of a numeric array, MATLAB expands the array to include those elements and fills the missing values with `0`.

```rng(1 , 'twister')
sampleMatrix3 = magic(3)
```

sampleMatrix3 =
8    1    6
3    5    7
4    9    2

```sampleMatrix3(3 , 4) = -10
```

sampleMatrix3 =
8    1    6    0
3    5    7    0
4    9    2    -10

Let’s see another example which affects the number of rows:

```rng(1 , 'twister')
sampleMatrix3 = magic(3)
```

sampleMatrix4 =
8    1    6
3    5    7
4    9    2

```sampleMatrix4(5 , 2) = -20
```

sampleMatrix3 =
8    1    6
3    5    7
4    9    2
0    0    0
0   -20   0

Exercise 1: We have a 3-by-7 matrix which is called `sampleMatrixE1`. We need to shift the matrix 3 columns to the left without changing the rows structure in a single line of code.

```  rng(1 , 'twister')
sampleMatrixE1 = randi(1000 , 3 , 7)
```

sampleMatrixE1 =
418    303    187    539    205    671    141
721    147    346    420    879    418    199
1      93     397    686    28     559    801

```  sampleMatrixE1(: , [4:end 1:3])
```

ans =
539    205    671    141    418    303    187
420    879    418    199    721    147    346
686    28     559    801    1      93     397

Another way is to use `circshift()` function which allows to shift a vector or array by `k` positions:

```   % doc circshift: positive k to shift to right,
% negative values to shift to left
circshift(sampleMatrixE1 , -3 , 2)
```

ans =
539    205    671    141    418    303    187
420    879    418    199    721    147    346
686    28     559    801    1      93     397

Exercise 2: We have a 4-by-8 numeric array with positive and negative elements. We want to remove the columns in which there is at list 1 negative value while preserving all the rows in only one line of code:

```  rng(1 , 'twister')
sampleMatrixE2 = randi(1000 , 4 , 8) - 100
```

sampleMatrixE2 =
318    47     297    105    318    701    777    70
621    -7     439    779    459    869    795    779
-99    87     320    -72    41     214    -14    -1
203    246    586    571    99     593    -60    322

Hint: you can use `sum()` function to solve this.

```  sampleMatrixE2(: , ~logical(sum(sampleMatrixE2 < 0 , 1)))
```

ans =
297    318    701
439    459    869
320    41     214
586    99     593

Exercise 3: Assume that we have a 4-by-4 array, which is `sampleMatrixE3`. We need to return the elements from the rows in which all numbers are larger than 100 AND columns in which all numbers are smaller than 800 in an only one line of code:

```  rng(1 , 'twister')
sampleMatrixE2 = randi(1000 , 4 , 8) - 100
```

sampleMatrixE3 =
418    147    397    205
721    93     539    879
1      187    420    28
303    346    686    671

Hint: you can use `sum()` function to solve this.

```  sampleMatrixE3(~(sum(sampleMatrixE3 > 100 , 2) ~= end) , ...
~(sum(sampleMatrixE3 < 800 , 1) ~= end))
```

ans =
418    147    397
303    346    686

Exercise 4: We have `sampleMatrixE4` and `sampleMatrixE5` arrays where the number of rows and columns of the first array is always higher than the second one. Assume that the two arrays are mapped as shown in the figure below: Exercise 4 of part 2

We want to return the elements of `sampleMatrixE4` where the mapped elements of `sampleMatrixE5` is greater than 500. You should be able to do it in 2 lines of code.

```  rng(1 , 'twister')
sampleMatrixE4 = randi(1000 , 5 , 5)
sampleMatrixE5 = randi(1000 , 3 , 3)
```

sampleMatrixE4 =
418    93     420    671    801
721    187    686    418    969
1      346    205    559    314
303    397    879    141    693
147    539    28     199    877

sampleMatrixE5 =
895    170    422
86     879    958
40     99     534

Hint: you’d probably need `ind2sub()` and `sub2ind()` functions.

```  [rows , cols] = ind2sub(size(sampleMatrixE5), ...
find(sampleMatrixE5 > 500))
```

rows =
1
2
2
3

cols =
1
2
3
3

```  sampleMatrixE4(sub2ind(size(sampleMatrixE4) , ...
rows + (size(sampleMatrixE4 , 1) - size(sampleMatrixE5 , 1)) , ...
cols + (size(sampleMatrixE4 , 2) - size(sampleMatrixE5 , 2))))
```

ans =
205
141
693
877