Explanation for matlab multidimensional indexing - matlab

Suppose I create the following matrix M.
>>>M = reshape(linspace(11,18,8),[2, 2, 2])
>>>M(:,:,1) =
11 13
12 14
M(:,:,2) =
15 17
16 18
>>>M([1,2],[2, 1],[2,1])
>>>
ans(:,:,1) =
17 15
18 16
ans(:,:,2) =
13 11
14 12
Please explain how the command M([1,2],[2, 1],[2,1]) produces the above result.explain the indexing in detail.

Let us start with simple example,
M([1,2],1,1) is going to show rows 1 and 2 of column 1 and 2d matrix 1.
ans =
11
12
M([2,1],1,1) is going to exchange rows 1 and 2 of column 1 and 2d matrix 1.
ans =
12
11
So changing the first index changes the rows order. Similarly Modifying second index will change the column order. And modifying third index will change the 2d matrices order.
Now let us take small example before we go to your problem,
M([1,2],[2,1],1)
Will exchange the columns of both rows of first 2d matrix.
ans =
13 11
14 12
And M([1,2],[1,2],[2,1]) will exchange between 1st 2d matrix and the second,
ans(:,:,1) =
15 17
16 18
ans(:,:,2) =
11 13
12 14
So combining the last two examples will exchange the 2d matrices and exchange their columns with keeping the orders of rows and that what exactly your answer shows
M([1,2],[2, 1],[2,1])
ans(:,:,1) =
17 15
18 16
ans(:,:,2) =
13 11
14 12

Hope this helps.
First, M is a three-dimensional matrix, which consists of two 2x2 matrix. So M(:,:,1) will get the first 2x2 matrix, and M(:,:,2) will get the second 2x2 matrix.
Some examples :
M(1, 2, 2) will give answer 17, which is the element in row 1 and column 2 of the 2nd matrix.
M(1, 1, [2, 1]) will give answers : 15 and 11 in that order. It will gather the element in row 1 and column 1, of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
M(1, 1, [1, 2]) will give answers : 11 and 15 in that order. It will gather the element in row 1 and column 1, of each from the two matrix in [1 2] order (so it will return from the 1st matrix first).
M(1, [1 2], [2, 1]) will give answers : 15 17 and 11 13 in that order. It will gather the element(s) in row 1 of column 1 & 2 (in this order), of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
M(2, [1 2], [2, 1]) will give answers : 16 18 and 12 14 in that order. It will gather the element(s) in row 2 of column 1 & 2 (in this order), of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
M(2, [1 1], [2, 1]) will give answers : 16 16 and 12 12 in that order. It will gather the element(s) in row 2 of column 1 & 1 (*same column), of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
So,
M([1 2], [2 1], [2, 1]) will give answers :
17 15
18 16
( which means the output is a 2x2 matrix, with 1st column and 2nd column are 2nd column and 1st column (respectively, by [2 1]) of the 2nd matrix. The 1st row and 2nd row are 1st and 2nd rows (respectively, by [1 2]) of the 2nd matrix. )
and also
13 11
14 12
....
Also, you may want to read the documentation : https://www.mathworks.com/help/matlab/math/matrix-indexing.html

Related

Rolling-window matrix with different intervals between columns

I have a vector of data for 21 years with daily data and want to create a rolling window of 365 days such as the next period stars one month (30 days) after the previous one. In the question, n_interval defines the difference between the first data point of the next window and the last observation of the previous series.
Let's assume my daily data start from Jan. 1 2000, then the first column would be Jan. 1, 2000 -Jan.1, 2001 and the second column starts from Feb. 1, 2000. and ends on Feb. 1, 2001. and ... the last column will cover Jan. 1, 2017 to Jan. 1, 2018. for example if:
vec = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
for a given variable n_interval = 3, with window_size=5, the output matrix should look like:
mat = [[1 4 7 10 13],
[2 5 8 11 14],
[3 6 9 12 15],
[4 7 10 13 16],
[5 8 11 14 17]]
Given your example vector
vec = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17];
we can create an indexing scheme by as follows:
First, we need to determine how many rows there will be in the mat. Assuming we want every element of vec to be expressed in mat at least once then we need to make sure that last index in the last row is greater than or equal to the size of vec. It's fairly easy to see that the index of the last column in mat is described by
last_index = n_interval*(n_rows-1) + n_columns
We want to ensure that last_index >= numel(vec). Substituting in the above expression into the inequality and solving for n_rows gives
n_rows >= (numel(vec) - n_columns)/n_interval + 1
We assign n_rows to be the ceil of this bound so that it is the smallest integer which satisfies the inequality. Now that we know the number of rows we generate the list of starting indices for each row
start_index = 1:n_interval:(n_interval*(n_rows-1)+1);
In the index matrix we want each column to be 1 plus the previous column. In other words we want to offset the column according to the array index_offset = 0:(n_interval-1).
Using bsxfun we generate the index matrix by computing the sums of all pairs between the start_index and index_offset arrays
index = bsxfun(#plus, index_offset, start_index');
The final thing we need to worry about is going out of bounds. To handle this we apply the mod function to wrap the out of bounds indicies:
index_wrapped = mod(index-1, numel(vec))+1;
Then we simply sample the vector according to index_wrapped
mat = vec(index_wrapped);
The complete code is
n_interval = 3;
n_columns = 5;
vec = 1:17;
n_rows = ceil((numel(vec)-n_columns)/n_interval + 1);
start_index = 1:n_interval:(n_interval*(n_rows-1)+1);
index_offset = 0:(n_columns-1);
index = bsxfun(#plus, index_offset, start_index');
index_wrapped = mod(index-1, numel(vec))+1;
mat = vec(index_wrapped);

What the meaning of this index in MATLAB?

data = reshape(1:21504,[256,4,21]);
data(:,5:4:end)
I test some indexes, such as:
data(:,5:4:end) ~= data(:,5:4:end,1)
data(:,5:4:end) ~= data(:,1,5:4:end)
So what is the meaning of data(:,5:4:end)?
I test some other indexes, such as:
data(1,1) == data(1,1,1)
data(1,1:3) == data(1,1:3,1)
And find some strange behavior ,such as data(1,1:10,1) returns error but data(1,1:10) is ok.
So What's happening here?
How can I understand this mechanism?
>> size(data)
ans =
256 4 21
data(1,1:10,1) selects column 1-10 from first row (all three dimensions are explicitly set), but there are only 4 columns. Therefore the error.
data(1,1:10), on the other hand, uses Linear indexing, which interpretes dimensions 2 and 3 as one long strung of values and selects its first 10 values.
Linear Indexing
What does this expression A(14) do?
When you index into the matrix A using only one subscript, MATLAB treats A as if its elements were strung out in a long column vector, by going down the columns consecutively, as in:
16
5
9
...
8
12
1
The expression A(14) simply extracts the 14th element of the implicit column vector. Indexing into a matrix with a single subscript in this way is often called linear indexing.
Here are the elements of the matrix A along with their linear indices:
matrix_with_linear_indices.gif
The linear index of each element is shown in the upper left.
From the diagram you can see that A(14) is the same as A(2,4).
The single subscript can be a vector containing more than one linear index, as in:
A([6 12 15])
ans =
11 15 12
Consider again the problem of extracting just the (2,1), (3,2), and (4,4) elements of A. You can use linear indexing to extract those elements:
A([2 7 16])
ans =
5 7 1
That's easy to see for this example, but how do you compute linear indices in general? MATLAB provides a function called sub2ind that converts from row and column subscripts to linear indices. You can use it to extract the desired elements this way:
idx = sub2ind(size(A), [2 3 4], [1 2 4])
ans =
2 7 16
A(idx)
ans =
5 7 1
(Copied from http://de.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html)
data(:, 5:4:end) will access all elements in the first dimension of data and starting from index 5 every 4th index until the last index in the second dimension of data. The syntax for this indexing technique can be explained like this:
data(startIndex:step:endIndex)
If data has more dimensions than you used for indexing, this will assume : for every dimension after that.
To sum up my question:
data=reshape(1:24,2,3,4)
data(:,:,1) =
1 3 5
2 4 6
data(:,:,2) =
7 9 11
8 10 12
data(:,:,3) =
13 15 17
14 16 18
data(:,:,4) =
19 21 23
20 22 24
Using this example you can know what Matlab doing:
data(:,1)
ans =
1
2
data(:,12)
ans =
23
24
data(:,[1,12])
ans =
1 23
2 24
data(:,5:4:end)
ans =
9 17
10 18
If you use data(:,13),it throws an error.

Finding index of vector from its original matrix

I have a matrix of 2d lets assume the values of the matrix
a =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
17 24 1 8 15
11 18 25 2 9
This matrix is going to be divided into three different matrices randomly let say
b =
17 24 1 8 15
23 5 7 14 16
c =
4 6 13 20 22
11 18 25 2 9
d =
10 12 19 21 3
17 24 1 8 15
How can i know the index of the vectors in matrix d for example in the original matrix a,note that the values of the matrix can be duplicated.
for example if i want to know the index of {10 12 19 21 3} in matrix a?
or the index of {17 24 1 8 15} in matrix a,but for this one should return only on index value?
I would appreciate it so much if you can help me with this. Thank you in advance
You can use ismember with the 'rows' option. For example:
tf = ismember(a, c, 'rows')
Should produce:
tf =
0
0
1
0
0
1
To get the indices of the rows, you can apply find on the result of ismember (note that it's redundant if you're planning to use this vector for matrix indexing). Here find(tf) return the vector [3; 6].
If you want to know the number of the row in matrix a that matches a single vector, you either use the method explained and apply find, or use the second output parameter of ismember. For example:
[tf, loc] = ismember(a, [10 12 19 21 3], 'rows')
returns loc = 4 for your example. Note that here a is the second parameter, so that the output variable loc would hold a meaningful result.
Handling floating-point numbers
If your data contains floating point numbers, The ismember approach is going to fail because floating-point comparisons are inaccurate. Here's a shorter variant of Amro's solution:
x = reshape(c', size(c, 2), 1, []);
tf = any(all(abs(bsxfun(#minus, a', x)) < eps), 3)';
Essentially this is a one-liner, but I've split it into two commands for clarity:
x is the target rows to be searched, concatenated along the third dimension.
bsxfun subtracts each row in turn from all rows of a, and the magnitude of the result is compared to some small threshold value (e.g eps). If all elements in a row fall below it, mark this row as "1".
It depends on how you build those divided matrices. For example:
a = magic(5);
d = a([2 1 2 3],:);
then the matching rows are obviously: 2 1 2 3
EDIT:
Let me expand on the idea of using ismember shown by #EitanT to handle floating-point comparisons:
tf = any(cell2mat(arrayfun(#(i) all(abs(bsxfun(#minus, a, d(i,:)))<1e-9,2), ...
1:size(d,1), 'UniformOutput',false)), 2)
not pretty but works :) This would be necessary for comparisons such as: 0.1*3 == 0.3
(basically it compares each row of d against all rows of a using an absolute difference)

How can a single matrix element be accessed in Matlab / Octave?

Suppose I have:
>> X = magic(5)
X =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
How do I get i'th element from the second column?
I already figured that indices in (some?) collections in Octave are one-based, but I'm not sure if that holds for matrices, too.
See the index expressions section of the manual. To get the i'th element from second column:
X(i,2) # element 'i' from column 2
X(1:end,2) # the whole 2nd column
X(:,2) # same thing but shorter
x(:, [2 3]) # whole 2nd and 3rd column
Note that Octave is a language where array elements are in column-major order.

Getting the indices of the max values of matrix columns in MATLAB

I need to get the indices of the maximum values of the columns in a matrix, for example:
a =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
and I want to get
[1, 4, 4, 1]
which are the indices of 16,14,15,13 i.e. the maximum value in each column. I discovered that
max(a,[],1)
returns
[16, 14, 15, 13]
How can I get their indices?
You need to find indices, not the numbers themselves, so you need the second output argument.
[~,I] = max(a)