Indexing – Mixing It Up
I've written a bunch of posts related to indexing, but I still haven't showed all the flexibility allowed. Today I'm going to add a variant to the list.
Contents
Types of Indexing - a Review
Let's start with indexing using subscripts. Let's start by creating a matrix.
A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
A = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
If I want to pick out the element sitting in the second row, third column, I simply write this
el23 = A(2,3)
el23 = 7
and you see result 7.
If I want another element as well, let's say 4th row, 2nd element, I can certainly follow my last statement with a similar one.
el42 = A(4,2)
el42 = 14
If I want both those elements extracted, I can try combining their respective row and column indices.
els = A([2 4],[3 2])
els = 7 6 15 14
What you see is that MATLAB returns the 4 intersections, not just the first row with the first column index, and same for second. Instead we get each row index combined with each column index. To get only the two elements we originally sought, we can convert the subscripts into another form of index, a linear index. With linear indexing, we think of an array as starting with the (1,1) element, and, going down each row, stringing out the elements into a long column. Then we use the count into that column vector, which has length equal to numRows * numCols. Use sub2ind to make the transformation.
linInds = sub2ind(size(A),[2 4],[3,2])
linInds = 10 8
and then use these to index back into A,
A(linInds)
ans = 7 14
getting exactly the values expected.
At least I hope they are the values you expected, instead of 10 and 8. Remember, MATLAB stores array values columnwise, i.e., column followed by column.
Combining Styles of Indexing
Now consider another situation, where you have a matrix and you only want certain columns extracted, depending on the value in the corresponding row. Perhaps, for example, you are using NaN as a placeholder and you only want columns 2 and 4 in rows that do not start with NaN.
One function that will be useful to us here is isnan, and the output of isnan is a logical array (think true and false). If I have a vector D like this,
D = [ 1 NaN 3 -4 NaN pi]'
D = 1 NaN 3 -4 NaN 3.1416
I can identify which entries have NaN values.
nanD = isnan(D);
whos nanD
nanD
Name Size Bytes Class Attributes nanD 6x1 6 logical nanD = 0 1 0 0 1 0
I can us logical indexing to extract the non-|NaN| entries in D.
nonNaND = D(~nanD)
nonNaND = 1 3 -4 3.1416
Combine Techniques
I am now ready to combine the ideas of logical indices and regular subscripts. Here's some data.
Data = rand(10,5)
Data = 0.81472 0.15761 0.65574 0.70605 0.43874 0.90579 0.97059 0.035712 0.031833 0.38156 0.12699 0.95717 0.84913 0.27692 0.76552 0.91338 0.48538 0.93399 0.046171 0.7952 0.63236 0.80028 0.67874 0.097132 0.18687 0.09754 0.14189 0.75774 0.82346 0.48976 0.2785 0.42176 0.74313 0.69483 0.44559 0.54688 0.91574 0.39223 0.3171 0.64631 0.95751 0.79221 0.65548 0.95022 0.70936 0.96489 0.95949 0.17119 0.034446 0.75469
Let me pull out columns 2 and 5, if the first column is at least 0.8. I'll leave the first column as well so you can trace what's happening.
extractD = Data(Data(:,1)>=0.8,[1 2 5])
extractD = 0.81472 0.15761 0.43874 0.90579 0.97059 0.38156 0.91338 0.48538 0.7952 0.95751 0.79221 0.70936 0.96489 0.95949 0.75469
Have You Combined Indexing Techniques?
If you have, what were you trying to accomplish when you mixed different kinds of indexing into a single array.
- Category:
- Indexing