Converting a matlab matrix to a vector - matlab

I want to get a vector of elements of a Matlab matrix at predefined locations. For example, I have the following
>> i = [1,2,3];
>> j = [1,3,4];
>> 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
I want a vector that will give me the values of A at the locations correspongin to i,j. I tried
A(i,j)
ans =
1 3 4
5 7 8
9 11 12
but this is not what I wanted. I want to get the following
>> [A(i(1),j(1)); A(i(2),j(2));A(i(3),j(3))]
ans =
1
7
12
What is the matlab syntax for that? Please, avoid suggesting for loops or anything that is not in a vectorized form, as I need this to be done fast. Hopefully there will be some built-in function.

to get it in the fastest way, use linear indexing:
A((j-1)*size(A,1)+i)
remember that MATLAB uses a column-major order.

A(sub2ind(size(A),i,j))
If you really crave speed, you might try making your own copy of sub2ind.m that strips out all the input-checking that that function does.

To understand how to do this, it is best to understand how matlab stores its arrays. In the matrix:
i = [1,2,3];
j = [1,3,4];
A = [1,2,3,4; 5,6,7,8; 9,10,11,12; 13,14,15,16]
matlab stores the elements going DOWN the columns. So they actually reside in memory in the order:
{1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16}
You can actually index a 2-d array using a SINGLE index. This is why the sub2ind trick works. Since the elements that you want to get are the 1st, 10th and 15th elements, as stored in a column-wise ordering,
singleIndex = [1 10 15];
A(singleIndex)
ans =
1 7 12
To confirm that sub2ind gave that index list, try it...
ind = sub2ind([4 4],i,j)
ind =
1 10 15

For now I'm using this:
>> diag(A(i,j))
ans =
1
7
12

Related

Shortest command to extract a submatrix using a vector containing the indexes of the 2 corners [matlab]

Let's say we have the following matrix
A=magic(4)
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
and we want to extract 3 submatrices, identified by the indexes for top left and bottom right corners. The indexes for a submatrix are contained in a row of the matrix i; columns 1 and 2 of i are the row indexes of the corners, columns 3 and 4 of i are the column indexes of the corners.
i.e.
i =
1 1 1 3
2 4 1 2
3 4 3 4
>> A(i(1,1):i(1,2),i(1,3):i(1,4))
ans =
16 2 3
>> A(i(2,1):i(2,2),i(2,3):i(2,4))
ans =
5 11
9 7
4 14
>> A(i(3,1):i(3,2),i(3,3):i(3,4))
ans =
6 12
15 1
The command A(i(,):i(,),i(,):i(,)) which I used to extract the submatrices is not very convenient, so I wonder is there a better way to do the job ?
If you don't want to type it all out then why not write a wrapper function?
A = magic(4);
S = #(r) A(i(r,1):i(r,2),i(r,3):i(r,4));
S(1)
S(2)
S(3)
If A may change after the definition of S then you would need to make it a parameter to the function.
S = #(A,r) A(i(r,1):i(r,2),i(r,3):i(r,4));
A = magic(4)
S(A,1)
S(A,2)
S(A,3)
Similarly if i may change then you would need to make it a parameter as well.
Edit
Unfortunately, contrary to my comment, if you want to perform assignment then A(I(r)) won't work exactly the same as what you've posted since this always returns an array instead of a matrix. One possible workaround is to use cell arrays in place of comma-separated-lists, but this isn't as elegant as the read only option. For example
S = #(r) {i(r,1):i(r,2) , i(r,3):i(r,4)};
s = S(1); A(s{:})
s = S(2); A(s{:})
s = S(3); A(s{:})
Following the same principle you could pre-define a cell array from i to make access one line.
s = arrayfun(#(r) {i(r,1):i(r,2),i(r,3):i(r,4)}, 1:size(i,1), 'UniformOutput', false);
A(s{1}{:})
A(s{2}{:})
A(s{3}{:})

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.

Creating a column of certain values from an array? Matlab [duplicate]

Suppose I had a 1-by-12 matrix and I wanted to resize it to a 4-by-3 matrix. How could I do this?
My current solution is kind of ugly:
for n = 1:(length(mat)/3)
out(n,1:3) = mat( ((n-1)*3 + 1):((n-1)*3 + 3) );
end
Is there a better way to do this?
reshape is of course the proper solution, as stated by #gnovice.
A nice feature of reshape is that it allows this:
A = 1:12;
B = reshape(A,4,[]);
B =
1 5 9
2 6 10
3 7 11
4 8 12
So if you don't know how many columns there will be, reshape will compute it for you. Likewise, reshape will fill in the number of rows, if you leave that out.
C = reshape(A,[],4)
C =
1 4 7 10
2 5 8 11
3 6 9 12
Try the RESHAPE function:
A = (1-by-12 matrix);
B = reshape(A,4,3);
Note that the matrix B will be filled with elements from A in a columnwise fashion (i.e. columns will be filled from top to bottom, moving left to right).
Example:
>> A = 1:12;
>> B = reshape(A,4,3)
B =
1 5 9
2 6 10
3 7 11
4 8 12
to extend gnovice's solution:
If you need a different order of matrix construction, use transpose (the ' operator) or permute() to change the dimension ordering after you have called reshape().

Define ranges for multiple values

I have two arrays
A=[1;2]
B= [5;6]
Now I want to have the matrix C = A:B such that
C = [1 2 3 4 5; 2 3 4 5 6]
How can I do this in matlab?
You can do this using arrayfun in combination with cell2mat like this:
A =
1 4 7 10
B =
5 8 11 14
cell2mat(arrayfun(#(n) (A(n):B(n)), 1:numel(A),'UniformOutput', false)')
ans =
1 2 3 4 5
4 5 6 7 8
7 8 9 10 11
10 11 12 13 14
You can shorten it down a bit using an abbreviation for UniformOutput, but I suggest writing it out since the abbreviations might no longer be unambiguous in future MATLAB versions. Check this question for a lengthy discussion on the topic.
Your question implicitly assumes that B(1)-A(1) equals B(2)-A(2) etc; otherwise the result is undefined.
You can do it quite generally and efficiently as follows: build the first row, and then use bsxfun to obtain all other rows:
C = bsxfun(#plus, A(1):B(1), A(:)-A(1));
C = [A(1,1):B(1,1);A(2,1):B(2,1)];
Try it:
C=[ A(1):1:B(1); A(2):1:B(2) ]

Matlab How to easily loop round array

Hi i'm looking for a way to take a slice of an array from the near the end to near the beginning. I know I could do this in two parts, then add them, but it seems like such a commonly desired operation I thought matlab probably already has it built in but I couldn't find any information in my search.
To clarify I would like to be able to say:
y = 1:10
y(-3:3) or y(8:3)
returns:
8 9 10 1 2 3
Thanks in advance.
there actually is a way to do it (without splitting it up in a concatenation of the negative and positive part of indices): use the modulo operator on your desired range:
>> y = 1:10;
>> y(mod([-3:3]-1,numel(y))+1)
ans =
7 8 9 10 1 2 3
This result consists of 7 numbers (opposing your desired [8 9 10 1 2 3]), which is logical because -3:3 actually spans 7 numbers.
The number 0 would correspond to y(end) with this method, -1 would correspond to y(end-1), etc.
You can try this:
y = 1:10;
n = 3;
y([end-n+1:end 1:n]);
This returns
ans =
8 9 10 1 2 3