matlab: how to create matrix by shift vector - matlab

I have row and column in matlab:
a = [1 0 3 ... a_k]; - row 1xk
b = [1;0;3; ... b_k]; - column kx1
I want to create new matrix's (A and B) mxn, that can be populate by shift row and column:
A = [1 0 3 0 0 0 0 ... 0;
0 1 0 3 0 0 0 ... 0;
0 0 1 0 3 0 0 ... 0;
...
0 0 0 0 0 0 ... 1 0 3 ]
B= [1 0 0 0 0 0 0 ... 0;
0 1 0 0 0 0 0 ... 0;
3 0 1 0 0 0 0 ... 0;
0 3 0 1 0 0 0 ... 0;
0 0 3 0 1 0 0 ... 0;
...
0 0 0 0 0 0 0 ... 3]
How can I do it?

Is this what you want?
>> a = [1 0 3];
>> m = 5; %// number of rows
>> A = convmtx(a,m)
A =
1 0 3 0 0 0 0
0 1 0 3 0 0 0
0 0 1 0 3 0 0
0 0 0 1 0 3 0
0 0 0 0 1 0 3
>> b = [1;0;3];
>> m = 4; %// number of columns
>> B = convmtx(b,m)
B =
1 0 0 0
0 1 0 0
3 0 1 0
0 3 0 1
0 0 3 0
0 0 0 3

You can do this in a slightly tricky way by using a combination of indexing and bsxfun. First we want to create an index matrix that represents the shift that we're trying to. It should look like this (at least for A):
1 2 3 4 ... k
k 1 2 3 ... k-1
etc
To create this, we can use bsxfun as follows:
index = mod(bsxfun(#plus,1:k,-(1:(k-2))'),k)+1;
We can then create the matrix A by using this as an index matrix for a:
A = a(index);
The matrix B is the same, just transposed:
B = b(index)';

Related

How to create a criss cross diagonal matrix

How to create a matrix like this
A = [a 0 0 0 0 b;
0 a 0 0 b 0;
0 0 a b 0 0;
0 0 b a 0 0;
0 b 0 0 a 0;
b 0 0 0 0 a]
Perhaps something like this
N = 6; % Size of matrix
a = 1; % Example value
b = 2; % Example value
A = a*eye(N) + b*fliplr(eye(N));
A =
1 0 0 0 0 2
0 1 0 0 2 0
0 0 1 2 0 0
0 0 2 1 0 0
0 2 0 0 1 0
2 0 0 0 0 1

In matlab, increment different column element for every row in without using a loop

Assume you have an 4x4 matrix A of zeros:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
And an 4x1 vector B that represents column indices for matrix A (so values [1:4])
4
2
3
1
Now I want to increment those columnpositions in matrix A on the index on every row from vector B.
I have tried a couple of constructions myself but can't quite manage to do this.
For example I tried:
A(:, B) = A(:, B)+1
Which just increment every element in A.
This is how I want the operation to act:
>> A(somethting(B)) = A(somethting(B)) + 1
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0
You can do this by using the linear index to each of the elements you want to address. Compute this using sub2ind:
>> A = zeros(4)
A =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
>> B = [4 2 3 1]
B =
4 2 3 1
>> i=sub2ind(size(A),B,1:4)
i =
4 6 11 13
>> A(i) = A(i)+1
A =
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0
Well just in case you want a looped version :p
A = zeros(4,4);
B = [4, 2, 3, 1];
for i = 1:length(B)
A(i, B(i) ) = A(i, B(i) ) + 1;
end
A = zeros(4);
B = [4 2 3 1];
A(repmat([1:4]',1,4) == repmat(B,4,1)) = 1
A =
0 0 0 1
0 1 0 0
0 0 1 0
1 0 0 0

what do the commas in (cl,:,k) in MATLAB do, when building a matrix

I know how to build a matrix within MATLAB but the example I am working on has is defined as
a(cl,:,k)=x*ang;
cl, k, x and ang are already defined. I just wondered what the (cl,:,k) does, in particular the role of the commas?
Also, if I were to replicate this within Excel then how would I do so?
The comma , in a(cl,:,k) is to separate different dimensions of the matrix a.
The colon : in a(cl,:,k) is to select all elements along this dimension (restricted by other dimensions), which is shorthand notation for 1:end. In other words, all elements a(cl, 1:end, k) are selected, where end is the size of the second dimension of a.
For example:
a = zeros(2, 3); // 2x3 matrix with all elements are 0
a(1, :) = [1 2 3]; // <=> a(1,1:3)=[1 2 3]; assign all elements to the first row
then, a will be
1 2 3
0 0 0
The commas separate the indices along different axes of the elements of the multi dimensional array you want to access
: means 1:end - here end will become the largest index possible along that axis
>> a = zeros(3,3,3)
a(:,:,1) =
0 0 0
0 0 0
0 0 0
a(:,:,2) =
0 0 0
0 0 0
0 0 0
a(:,:,3) =
0 0 0
0 0 0
0 0 0
>> a(1,:,1) = 1
a(:,:,1) =
1 1 1
0 0 0
0 0 0
a(:,:,2) =
0 0 0
0 0 0
0 0 0
a(:,:,3) =
0 0 0
0 0 0
0 0 0
>> a(2,1:end,2) = 2
a(:,:,1) =
1 1 1
0 0 0
0 0 0
a(:,:,2) =
0 0 0
2 2 2
0 0 0
a(:,:,3) =
0 0 0
0 0 0
0 0 0
>> a(1,1,:) = 5
a(:,:,1) =
5 1 1
0 0 0
0 0 0
a(:,:,2) =
5 0 0
2 2 2
0 0 0
a(:,:,3) =
5 0 0
0 0 0
0 0 0

Identify sequences of the same number in a matrix

I have matrix A
A= [0 0 2 2 2 2 0 0 1 1 1 0 3 3;
2 2 2 2 0 0 1 1 1 0 0 3 3 0;
As you can see, there are consecutive numbers in it; notice for example the 2 2 2 2 on the first and second row.
For each number occuring in this matrix (or at least for every number from 1 to the maximum number in my matrix) I want to have an output matrix that indicates sequences of this number and this number only in the original matrix.
So for example, for 1: there are three consecutive numbers on the first row and three on the second row: I want to indicate this in the first output matrix as follows:
Matrix 1 = [ 0 0 0 0 0 0 0 0 1 2 3 0 0 0;
0 0 0 0 0 0 0 1 2 3 0 0 0 0]
Same for number 2:
Matrix 2 = [ 0 0 1 2 3 4 0 0 0 0 0 0 0 0;
1 2 3 4 0 0 0 0 0 0 0 0 0 0]
and 3:
Matrix 3 = [ 0 0 0 0 0 0 0 0 0 0 0 0 1 2;
0 0 0 0 0 0 0 0 0 0 0 1 2 0]
As you can see, each output matrix shows counting forward for the consecutive occurrences of a number.
So in this case, I have 3 output matrices because matrix A has 3 as the biggest value there.
You can try this:
A= [0 0 2 2 2 2 0 0 1 1 1 0 3 3;
2 2 2 2 0 0 1 1 1 0 0 3 3 0];
result = arrayfun(#(b) (A == b).*cumsum((A == b),2),nonzeros(unique(A)), 'UniformOutput', false);
For this example, there will be 3 submatrices in the variable result.
result =
[2x14 double]
[2x14 double]
[2x14 double]
To access them, use the following syntax:
result{1}
result{2}
result{3}
Then you get:
ans =
0 0 0 0 0 0 0 0 1 2 3 0 0 0
0 0 0 0 0 0 1 2 3 0 0 0 0 0
ans =
0 0 1 2 3 4 0 0 0 0 0 0 0 0
1 2 3 4 0 0 0 0 0 0 0 0 0 0
ans =
0 0 0 0 0 0 0 0 0 0 0 0 1 2
0 0 0 0 0 0 0 0 0 0 0 1 2 0
~edit~
If, as asked in the comments, A is a 3D matrix, this code works just the same, but the structure of result is a bit different:
result =
[2x14x2 double]
[2x14x2 double]
[2x14x2 double]
To access these matrices, use for instance
result{1}(:,:,1) % for the results of comparing A(:,:,1) with value 1
result{1}(:,:,2) % for the results of comparing A(:,:,2) with value 1
Edited because the question changed
This is nowhere near to optimal but will do what you want
V = 1;
C = A' == V;
D = cumsum(C).*C
E = D'
now E will be Matrix1 in your example. Change V to 2 and 3 to obtain Matrix2 and Matrix3. If you have something like
A = [2 2 2 0 0 0 0 0 2 2 2]
then you will get
[1 2 3 0 0 0 0 0 4 5 6]
so it may not be what you want. It is not clear from your question if this is the case or not, but if not tell me and I will delete the answer
This is a loop-based solution to get you started:
A = [
0 0 2 2 2 2 0 0 1 1 1 0 3 3;
2 2 2 2 0 0 1 1 1 0 0 3 3 0
];
mx = max(A(:));
AA = cell(mx,1);
for num=1:mx
AA{num} = zeros(size(A));
for r=1:size(A,1)
idx = ( A(r,:) == num );
AA{num}(r,idx) = sum(idx):-1:1;
end
end
The result:
>> AA{1}
ans =
0 0 0 0 0 0 0 0 3 2 1 0 0 0
0 0 0 0 0 0 3 2 1 0 0 0 0 0
>> AA{2}
ans =
0 0 4 3 2 1 0 0 0 0 0 0 0 0
4 3 2 1 0 0 0 0 0 0 0 0 0 0
>> AA{3}
ans =
0 0 0 0 0 0 0 0 0 0 0 0 2 1
0 0 0 0 0 0 0 0 0 0 0 2 1 0
EDIT:
Updated code to work on matrix with three dimensions:
A = zeros(2,7,2);
A(:,:,1) = [2 2 2 0 0 1 1 ; 0 0 2 2 2 1 1];
A(:,:,2) = [1 1 2 2 2 0 0 ; 0 1 1 0 2 2 2];
mx = max(A(:));
AA = cell(mx,1);
for num=1:mx
AA{num} = zeros(size(A));
for p=1:size(A,3)
for r=1:size(A,1)
idx = ( A(r,:,p) == num );
AA{num}(r,idx,p) = 1:sum(idx);
end
end
end
The result:
%# contains consecutive numbers corresponding to number 1 in all slices
>> AA{1}
ans(:,:,1) =
0 0 0 0 0 1 2
0 0 0 0 0 1 2
ans(:,:,2) =
1 2 0 0 0 0 0
0 1 2 0 0 0 0
%# contains consecutive numbers corresponding to number 2 in all slices
>> AA{2}
ans(:,:,1) =
1 2 3 0 0 0 0
0 0 1 2 3 0 0
ans(:,:,2) =
0 0 1 2 3 0 0
0 0 0 0 1 2 3

Transform vector with repeating values into a matrix in Matlab

I have a vector of n size, which I would like to transform into the Boolean matrix of nxm, where m is a number of unique values in that vector.
a = repmat(1:5:20,1,3)
a =
1 6 11 16 1 6 11 16 1 6 11 16
The result I would like to have is the matrix 12x4:
1 0 0 0
0 1 0 0
0 0 1 0
...
0 0 0 1
Any ideas how to do that without for loop?
You can try this:
a = repmat(1:5:20,1,3);
b = unique(a);
bsxfun(#eq, a', b)
The result would be:
ans =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
a = repmat(1:5:20,1,3)
b=unique(a);
c = repmat(a',1,numel(b))== repmat(b,numel(a),1);
but in general a loop will be faster, repmat is to be avoided.
So, now with a loop:
a = repmat(1:5:20,1,3)
b=unique(a);
c=false(numel(a),numel(b));
for ii=1:numel(a)
c(ii,:) = a(ii)==b;
end