Find multiple row and column combinations in a matrix in Matlab - matlab

I have the following matrix:
>> MatrixA = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
MatrixA =
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
I want to find the following:
for row 1, I want the 2nd column
for row 2, I want the 3rd column
for row 3, I want the 4th column
for row 4, I want the 4th column
Currently I accomplish this with the following line:
>>diag(MatrixA([1 2 3 4], [2 3 4 4]))
ans =
2
7
12
16
Is there a more direct way to do this (without using diag)?

Well you could use sub2ind, it might be more intuitive. I don't think there is much benefit though, maybe it's more readable:
ind = sub2ind(size(MatrixA), [1 2 3 4], [2 3 4 4])
MatrixA(ind)

Related

Rearrange vector every nth column

Let's say I have a vector:
A=[1 2 3 6 7 8 11 12 13]
and I'm trying to achieve final output like:
[1 6 11 2 7 12 3 8 13]
Where the vector is rearranged to front every nth column, in this case, 3rd. Using indexing will work, but it requires a loop, which I'm trying to avoid. Any idea how to do it in a vectorized way? Thanks!
nth=3;
for i=1:nth:size(A,2)
A_(:,nth)= A(:,i:nth:end)
end
The suggestion that #jodag posted in the comments works totally fine. Alternatively, this should also do the job... but the constraint is the same, A must be divisible by nth:
nth = 3;
A = [1 2 3 6 7 8 11 12 13];
A_len = numel(A);
A_div = floor(A_len / nth);
seq = repmat(1:nth:A_len,1,A_div);
inc = sort(repmat(0:nth-1,1,A_div));
A = A(seq + inc)
Output:
A =
1 6 11 2 7 12 3 8 13

How to take union of matrix rows that are represented by another vector?

I want to take the union of some of the rows of a matrix x. The row numbers of the rows whose union has to be taken are given by vector r. Is there any built-in function in MATLAB that can do it?
x = [1 2 4 0 0;
3 6 5 0 0;
7 8 10 12 9;
2 4 6 7 0;
3 4 5 8 12];
r = [1, 3, 5];
I think this will work for you - first, take the submatrix x(r,:) with the rows you want, and then find all the unique values in it:
unique(x(r,:))
ans =
0
1
2
3
4
5
7
8
9
10
12
You could do it like this
>>> union(union(x(r(1),:),x(r(2),:)),x(r(3),:))
ans =
0 1 2 3 4 5 7 8 9 10 12
or set up a for loop that iterates over the vector r to compute all the unions

index matrix with array

I'd like to index matrix
x=[1:5;6:10]
x =
1 2 3 4 5
6 7 8 9 10
using array
[1,2,1,2,1]
to get
1 7 3 9 5
I tried this:
x([1,2,1,2,1],:)
ans =
1 2 3 4 5
6 7 8 9 10
1 2 3 4 5
6 7 8 9 10
1 2 3 4 5
but that is not what I want. Please help
I'd use linear indexing with sub2ind:
>> v = x(sub2ind(size(x),a,1:5))
v =
1 7 3 9 5
Let
ind = [1, 2, 1, 2, 1];
offset = [1:size(x, 1):numel(x)] - 1;
then
x(ind + offset)
returns what you want. This assumes that your index vector has an entry for every column of x and uses linear indexing to add a column offset to every in-column index.

getting all possibilities from 2 matrix

I'm trying to get all possible outcome from 2 different dimension matrix.
say,
A=[1 2 3 4;2 3 4 5]
and
B=[11 12; 13 14; 15 16]
with the output of
C=[1 2 3 4 11 12; 1 2 3 4 13 14; 1 2 3 4 15 16; 2 3 4 5 11 12; 2 3 4 5 13 14; 2 3 4 5 15 16]
I have tried using for loop method but I find it very inefficient and would therefore like to have a better approach to it.
Thanks.
If the repetition of matrix A is always a the number of rows of matrix B and repetition of matrix B is always the number of rows of A. Then, you can use the functions kron and repmat to achieve what you wanted. So, in this example, C can be obtained with a single line as
[kron(A, ones(size(B, 1), 1)) repmat(B, [size(A, 1) 1])]
You can use indexing to achieve this by
C=[A(repmat(1:size(A,1), 1, size(B,1)), :) B(repmat(1:size(B,1), 1, size(A,1)), :)];
A more readable version is
[X,Y]=meshgrid(1:size(A,1), 1:size(B,1));
C=[A(X(:),:) B(Y(:),:)];

Ranges with different step size for odd and even steps in MATLAB

What is the fastest and the simplest way to generate an array like
[0, 1, 3, 4, 6, 7, 9, 10, ...]
in MATLAB?
You can obtain the cumulative sum of the vector of steps (in your case it is [1 2 1 2 1 2 1 2 ...]). For example:
x = cumsum([0, repmat([1 2], 1, 4)])
x =
0 1 3 4 6 7 9 10 12
You can generate matrix with two rows: top row for odd array elements, bottom row for even elements. Than transform matrix into array with reshape.
>> a=[0:3:15; 1:3:16]
a =
0 3 6 9 12 15
1 4 7 10 13 16
>> a=reshape(a,1,12)
a =
0 1 3 4 6 7 9 10 12 13 15 16
Not one line but will work for either an odd or even number of total elements, and could be expanded if you wanted more than two different steps:
a = zeros(1,8);
a(1:2:end) = 0:3:10;
a(2:2:end) = 1:3:10;
Here is a simple and compact way:
A = 0:20;
A(3:3:end) = []