Matlab matrices dimension - matlab

I am new to matlab and just wondering if you guys can help me out with this problem.
For instance, I have two matrices:
A = [X1 X2 X3 X4]
B = [Y1; Y2; Y3]
now what I really want to achieve is to multiply these two matrices in this way:
[X1Y1 X2Y1 X3Y1 X4Y1;
X1Y2 X2Y2 X3Y2 X4Y2;
X1Y3 X2Y3 X3Y3 X4Y3;
.... and so on]
I tried using A(1,:).*B(:,1) but matlab is saying that matrix dimensions must agree.
I just don't know how to manipulate this on matlab but in excel is possible.

This is a simple outer product. kron is not needed (although it will work.) bsxfun is wild overkill, although will yield what you have asked for. repmat is inappropriate, because while it will help you do what you wish, it replicates the arrays in memory, using more resources than are needed. (Avoid using inefficient programming styles when there are good ones immediately at your disposal.)
All you need use is the simple * operator.
A is a row vector. B a column vector.
C = B*A
will yield the result C(i,j)=B(i)*A(j), which is exactly what you are looking for. Note that this works because B is 3x1 and A is 1x4, so the "inner" dimensions of B and A do conform.
In MATLAB, IF you are unsure if something works, TRY IT!
A = [1 2 3 4];
B = [1;2;3];
C = B*A
ans =
1 2 3 4
2 4 6 8
3 6 9 12
See that kron did indeed work, although I'd bet that use of kron here is probably less efficient than is the simple outer product multiply.
C = kron(B,A)
C =
1 2 3 4
2 4 6 8
3 6 9 12
As well, bsxfun will work here too, although since we are using a general tool to do something that a basic operator will do, I'd bet it is slightly less efficient.
C = bsxfun(#times,B,A)
C =
1 2 3 4
2 4 6 8
3 6 9 12
The WORST choice is repmat. Again, since it artificially replicates the vectors in memory FIRST, it must go out and grab big chunks of memory in the case of large vectors.
C = repmat(B,1,4).*repmat(A,3,1)
C =
1 2 3 4
2 4 6 8
3 6 9 12
I suppose for completeness, you could also have used meshgrid or ndgrid. See that it is doing exactly what repmat did, but here it explicitly creates new matrices. Again, this is a poor programming style when there are good tools to do exactly what you wish.
[BB,AA] = ndgrid(B,A)
BB =
1 1 1 1
2 2 2 2
3 3 3 3
AA =
1 2 3 4
1 2 3 4
1 2 3 4
C = BB.*AA
C =
1 2 3 4
2 4 6 8
3 6 9 12
What you need to understand is exactly why each of these tools COULD have been used for the job, and why they are different.

In Matlab there is * and .* and they are very different.
* is normal matrix multiplication which is what you want i.e. B*A, note the B must come first as the inner dimension must match. You can multiply a column by a row but not a row by a column (unless they have the same number of elements).
.* is element by element multiplication in which case the matrices must be exactly the same size and shape so for example [1 2 3].*[4 5 6] = [1*4 2*5 3*6] = [4 10 18]

Do not do a ".*". You should rather do a "*".
The ".*" is for index by index multiplication and should have given you [X1Y1 X2Y2 X3Y3] were they vectors have been equal in size.
If you do the regular multiplication "*", this is actually matrix multiplication.

I think you just need to transpose one of the vectors. You are multiplying a column vector (A(1,:)) with a row vector (B(:,1)). This should work:
C = A(1,:).*B(:,1)';

Related

how to reverse the element of matrix?

I am trying to reverse the elements of the matrix such that for given matrix order of the elements get reversed.
my code is as shown for the 3x3 matrix is working.
X = [ 1 2 3 ; 4 5 6 ; 7 8 9 ];
B = [fliplr(X(3,:));fliplr(X(2,:));fliplr(X(1,:))];
input X =
1 2 3
4 5 6
7 8 9
output:
B =
9 8 7
6 5 4
3 2 1
the above code I am trying to generalize for any matrix with the following code
[a,b]=size(X);
for i=0:a-1
A = [fliplr(X(a-i,:))];
end
but get only last row as output.
output A =
3 2 1
please help me to concatenate all the rows of the matrix one above to each other after it got reversed.
rot90 is the function made for this purpose.
B = rot90(A,2);
Your code doesn't work because you overwrite A in every loop iteration. Instead, you should index into A to save each of your rows.
However, fliplr can flip a whole matrix. You want to flip left/right and up/down:
B = flipud(fliplr(X));
This is the same as rotating the matrix (as Sardar posted while I was writing this):
B = rot90(X,2);
A totally different approach would work for arrays of any dimensionality:
X(:) = flipud(X(:));

Finding the most recent indices with different values

I am familiar with Matlab but am still having trouble with vectorized methods in my intuition, so I was wondering if anyone could demonstrate how they would manage this problem.
I have an array, for example A = [1 1 2 2 1 3 3 3 4 3 4 4 5].
I want to return an array B such that each element is the index of A's most 'recent' element with a different value than the previous ones.
So for our array A, B would equal [x x 2 2 4 5 5 5 8 9 10 10 12], where the x's can be any consistent value you like, because there is no previous index satisfying those characteristics.
I know how I would code it as a for-loop, and I bet the for-loop is probably faster, but can anyone vectorize this to faster than the for-loop?
Here's my for-loop:
prev=0;
B=zeros(length(A),1);
for i=2:length(A)
if A(i-1)~=A(i)
prev=i-1;
end
B(i)=prev;
end
Find the indices of the entries where the value changes:
ind = find(diff(A) ~= 0);
The values that should appear in B are therefore:
val = [0 ind];
Construct the diff of B: fill in the difference between the values that should appear at the right places:
Bd = zeros(size(B))';
Bd(ind + 1) = diff(val);
Now use cumsum to construct B:
B = cumsum(Bd)
Not sure whether this results in a speed-up though.

How to do rank-1 factorization in MATLAB?

I have a matrix M of dimensions 6x6 and it has rank 1. How can I factorize it into two matrices of dimensions 6x1 (say A) and 1x6 (say B) so that M=A*B.
take the largest eigen vector and multiply it by the largest eigenvalue :
A=[1 2 3 4]'*[1 2 3 4]
A =
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
[v,e] = eigs(A,1);
sqrt(e)*v
ans =
-1.0000
-2.0000
-3.0000
-4.0000
of course, the result is good only up to a sign change.
EDIT:
if you assume that the two vectors can be different:
A=[1 2 3 4]'*[5 6 7 8]
[uu,ss,vv]=svd(A);
u=uu(:,1)*ss(1,1)
v=vv(:,1)
assert(norm(u*v'-A)<1E-10)
Now the solution is even less unique. You are determining 2*n values based on only n. This is one solution among many.
For example, look at this other even simpler solution (which will assume your matrix is perfectly rank 1) :
aa=A(:,:)./repmat(A(1,:),[size(A,1),1]);
bb=A(:,:)./repmat(A(:,1),[1,size(A,2)]);
u=aa(:,1);
v=bb(1,:)'*A(1);
assert(norm(u*v'-A)<1E-10)
it produces a totally different result, but that still factorizes the matrix. If you want non-negative factorizations only to slightly reduce the space of possible results, I'd suggest you ask a new question!
If it has rank 1, then all columns/rows are multiples of the first column/row (or indeed of any non-zero column/row). i.e.:
m = M(:,1);
M = [ a*m, b*m, c*m, d*m, e*m, f*m ];
Hopefully you can take it from there.

MATLAB search row index of matrix with values of another matrix

In MATLAB I have a very large matrix (matrix A). Now I would like to find the row-index of the row which contain certain values in the second column. These values - which I'm looking for in Matrix A - are stored in anonther Matrix (Matrix B) with consists out of a row (800 numbers).
Besides I would like to redo this calculation for the same matrix A, but for ten different matrices, with different sizes (which contain the values I'm looking for in different columns of matrix A).
Because of the sizes of the matrix I think i need a loop to extract the row in matrix A which contain te value of Matrix B. How can I do this?
regards,
V
Thanks for the quick response! Indeed the problem is maybe a bit complex to answer without an example, and indeed duplicate entries cause some problems. Therefore hereby an example
For example I have a -simplified- matrix A:
1 2 3 4
9 9 9 9
4 3 2 1
And a -simplified- matrix (row) B: [9 3]
And a -simplified- matrix (row) C: [9 2]
Then I would like to get matrix D and matrix E.These matrices should contain in the first column the numbers from the original matrix D(or E) and in the second column the corresponding row-location of this value in matrix A.
So, matrix D =
9 2
3 3
matrix E =
9 2
2 3
As represented in this example matrix B and matrix C can contain data which is present in several column of matrix A (like the nine). However, martix B should "search" in column 2 of matrix A. Likewise, should matrix C "search" in column 3 of Matrix A, resulting in matrix D and E as given in the example.
As mentionned by Shai in his comment, your question is quite vague and a lot of special case could arise (duplicate entries, relative size of A and B, etc.). But in all generality I tried a small piece of code that seems to do what you want. There are certainly quicker ways of doing it, and certainly more information on your problem could help optimize this.
colA=2;
% Example
nmax=10;
nA=5;
A=randi(nmax,[nA nA]);
nB=3;
B=randi(nmax,[1 nB]);
% Find rows
rows=cell(size(B));
for i=1:numel(B)
rows(i)={find(A(:,colA)==B(i))};
end
The input / output was:
A =
3 7 8 5 4
9 7 3 7 5
8 2 9 9 8
9 5 9 7 9
3 3 4 6 8
B =
1 7 5
rows =
[0x1 double] [1;2] [4]
Assuming you have two vectors, largeDataIndex (the second column of your matrix) and interestingIndex (your b) and you want the following:
For each value of interestingIndex , find the position in largeDataIndex
Then an easy method would be this:
result = zeros(size(interestingIndex))
for i = 1:length(result)
result(i) = find(interestingIndex(i) == largeDataIndex)
end
Note that this assumes there is always just one entry that matches, otherwise you should define result as a cell array rather than a vector.

create new vectors from columns of an existing matrix

I'd like to create new vectors from columns of an existing matrix. My code looks like:
Matrix=[1 2 3;4 5 6;7 8 9];
A=Matrix(:,1);
B=Matrix(:,2);
C=Matrix(:,3);
I see that this code is not really elegant especially if I have a big number of columns, that's why I'm looking for something like:
[A B C]=Matrix;
But Matlab said the matrix can't be assigned to multiple values. Is there another way?
use mat2cell to split your original matrix up and deal to assign the splitted data to the result variables A,B and C:
m = mat2cell(Matrix,size(Matrix,1),ones(1,size(Matrix,2)))
[A,B,C] = deal(m{:})
Unfortunately the intermediary variable is needed (however there is the FEX function dealcell that solves this if you like one-liners)
Why would you want to do this? (Just curious) Matlab is designed to work off of a matrix. Hence the name Matrix Labratory... But alas it is still possible.
I'm sure there's a more elegant solution but I'll let you ponder that. This should get you going.
Matrix=[1 2 3;4 5 6;7 8 9];
for i=1:size(Matrix,2) %number of rows
eval(sprintf('A%d = Matrix(:,i)', i));
end
A1 =
1
4
7
A2 =
2
5
8
A3 =
3
6
9