Reshaping 3 dimensional array to 2 by stacking matrixes horizontally [duplicate] - matlab

This question already has an answer here:
Reshape matrix from 3d to 2d keeping specific order
(1 answer)
Closed 5 years ago.
I have 4x3x2 array:
A(:,:,1) =
1 10 100
2 20 200
3 30 300
4 40 400
A(:,:,2) =
5 50 500
6 60 600
7 70 700
8 80 800
I want to reshape it to B matrix with size 8x3 preserving the structure of each matrix as:
B =
1 10 100
2 20 200
3 30 300
4 40 400
5 50 500
6 60 600
7 70 700
8 80 800
Any idea how to do it in a simple and neat way?

As seen here.
Method 1: permute and reshape
B = reshape(permute(A, [2 1 3]), size(A, 2), [])'
Method 2: cell -> matrix
B = num2cell(A, [1 2]);
B = vertcat(B{:})

Related

Matlab - Merge two vectors and a matrix with different dimensions

I have two vectors and matrix, for example:
a = [ 1 2 3 4];
b = [6 7 8];
c = [ 600 700 800 900;
100 200 300 400;
777 888 555 333];
I would like to get a matrix as:
1 6 600
2 6 700
3 6 800
4 6 900
1 7 100
2 7 200
3 7 300
4 7 400
1 8 777
2 8 888
3 8 555
4 8 333
Is it possible to get this matrix without using loops?
Sure, with meshgrid for instance:
[B, A] = meshgrid(b, a);
C = c';
Res = [A(:) B(:) C(:)];
Best,

Sorting data in MATLAB dependant on one column

How do I sort a column based on the values in another column in MATLAB?
Column A shows position data (it is neither ascending or descending in order) Column B contains another column of position data. Finally column C contains numerical values. Is it possible to link the first position value in B with its numerical value in the first cell of C? Then after this I want to sort B such that it is in the same order as column A with the C values following their B counterparts?The length of my columns would be 1558 values.
Before case;
A B C
1 4 10
4 1 20
3 5 30
5 2 40
2 3 50
After Case;
A B C
1 1 20
4 4 10
3 3 50
5 5 30
2 2 40
Basically A and B became the same and Column C followed B.
Since you don't want things necessarily in ascending or descending order, I don't think any built-in sorting functions like sortrows() will help here. Instead you are matching elements in one column with elements in another column.
Using [~,idx]=ismember(A,B) will tell you where each element of B is in A. You can use that to sort the desired columns.
M=[1 4 10
4 1 20
3 5 30
5 2 40
2 3 50];
A=M(:,1); B=M(:,2); C=M(:,3);
[~,idx]=ismember(A,B);
sorted_matrix = [A B(idx) C(idx)]
Powerful combo of bsxfun and matrix-multiplication solves it and good for code-golfing too! Here's the implementation, assuming M as the input matrix -
[M(:,1) bsxfun(#eq,M(:,1),M(:,2).')*M(:,2:3)]
Sample run -
>> M
M =
1 4 10
4 1 20
3 5 30
5 2 40
2 3 50
>> [M(:,1) bsxfun(#eq,M(:,1),M(:,2).')*M(:,2:3)]
ans =
1 1 20
4 4 10
3 3 50
5 5 30
2 2 40
Given M = [A B C]:
M =
1 4 10
4 1 20
3 5 30
5 2 40
2 3 50
You need to sort the rows of the matrix excluding the first column:
s = sortrows(M(:,2:3));
s =
1 20
2 40
3 50
4 10
5 30
Then use the first column as the indices to reorder the resulting submatrix:
s(M(:,1),:);
ans =
1 20
4 10
3 50
5 30
2 40
This would be used to build the output matrix:
N = [M(:,1) s(M(:,1),:)];
N =
1 1 20
4 4 10
3 3 50
5 5 30
2 2 40
The previous technique will obviously only work if A and B are permutations of the values (1..m). If this is not the case, then we need to find the ranking of each value in the array. Let's start with new values for our arrays:
A B C
1 5 60
6 1 80
9 6 60
-4 9 40
5 -4 30
We construct s as before:
s = sortrows([B C]);
s =
-4 30
1 80
5 60
6 60
9 40
We can generate the rankings one of two ways. If the elements of A (and B) are unique, we can use the third output of unique as in this answer:
[~, ~, r] = unique(A);
r =
2
4
5
1
3
If the values of A are not unique, we can use the second return value of sort, the indices in the original array of the elements in sorted order, to generate the rank of each element:
[~, r] = sort(A);
r =
4
1
5
2
3
[~, r] = sort(r);
r =
2
4
5
1
3
As you can see, the resulting r is the same, it just takes 2 calls to sort rather than 1 to unique. We then use r as the list of indices for s above:
M = [A s(r, :)];
M =
1 1 80
6 6 60
9 9 40
-4 -4 30
5 5 60
If you must retain the order of A then use something like this
matrix = [1 4 10; 4 1 20; 3 5 30; 5 2 40; 2 3 50];
idx = arrayfun(#(x) find(matrix(:,2) == x), matrix(:,1));
sorted = [matrix(:,1), matrix(idx,2:3)];

how to multiply 2D slices of two 3D matrices with each other in Matlab

I have two 3D matrices A(kl,1,r) and B(1,rs,r). kl=rs.
I need to get a new matrix C(kl,rs,r) which should have the product of column vector of A(kl,1) by the row vector of B(1,rs) for every page r without for loop
C=zeros(size(A,1),size(B,2),r);
for rr=1:size(A,3)
dummy=squeeze(A(:,:,rr))*squeeze(B(:,:,rr))';
C(:,:,rr)=dummy;
end
can anyone help with that? :)
Using bsxfun, you could do that directly in one line
out = bsxfun(#times, A, B);
Sample Inputs:
>> A
A(:,:,1) =
6
10
3
A(:,:,2) =
2
2
1
>> B
B(:,:,1) =
5 5 4
B(:,:,2) =
8 7 8
Results:
out(:,:,1) =
30 30 24
50 50 40
15 15 12
out(:,:,2) =
16 14 16
16 14 16
8 7 8

Multiply each value in rows of Matrix A by each corresponding value of a specfic row in Matrix B

I have a A=[m,n] matrix and a B=[n,l] matrix.
A =
[1 2 3
4 5 6
7 8 9
10 11 12]
For the sake of simplicity, let's assume l=1, so B is in fact a vector B=[n,1]
B = [100 10 1]
I would like multiply all the values in each row of A by a corresponding value of B - column-wise.
I know how to do it "manually":
C=[A(:,1)*B(:,1), A(:,2)*B(:,2), A(:,3)*B(:,3)]
This is the result I want:
C = [100 20 3
400 50 6
700 80 9
1000 110 12]
Unfortunately my real life matrices are a bit bigger e.g. (D=[888,1270]) so I'm looking for smarter/faster way to do this.
Pre R2016b:
C=bsxfun(#times,A,B)
C =
100 20 3
400 50 6
700 80 9
1000 110 12
R2016b and later:
In MATLABĀ® R2016b and later, you can directly use operators instead of bsxfun , since the operators independently support implicit expansion of arrays.
C = A .* B
If I > 1, then you will have to reorder the dimensions of B first with a permute,
>> B = [100 10 1; 1 10 100];
>> C = bsxfun(#times, A, permute(B, [3 2 1]));
>> C
C(:,:,1) =
100 20 3
400 50 6
700 80 9
1000 110 12
C(:,:,2) =
1 20 300
4 50 600
7 80 900
10 110 1200

How can I divide each row of a matrix by a fixed row?

Suppose I have a matrix like:
100 200 300 400 500 600
1 2 3 4 5 6
10 20 30 40 50 60
...
I wish to divide each row by the second row (each element by the corresponding element), so I'll get:
100 100 100 100 100 100
1 1 1 1 1 1
10 10 10 10 10 10
...
Hw can I do it (without writing an explicit loop)?
Use bsxfun:
outMat = bsxfun (#rdivide, inMat, inMat(2,:));
The 1st argument to bsxfun is a handle to the function you want to apply, in this case right-division.
Here's a couple more equivalent ways:
M = [100 200 300 400 500 600
1 2 3 4 5 6
10 20 30 40 50 60];
%# BSXFUN
MM = bsxfun(#rdivide, M, M(2,:));
%# REPMAT
MM = M ./ repmat(M(2,:),size(M,1),1);
%# repetition by multiplication
MM = M ./ ( ones(size(M,1),1)*M(2,:) );
%# FOR-loop
MM = zeros(size(M));
for i=1:size(M,1)
MM(i,:) = M(i,:) ./ M(2,:);
end
The best solution is the one using BSXFUN (as posted by #Itamar Katz)
You can now use array vs matrix operations.
This will do the trick :
mat = [100 200 300 400 500 600
1 2 3 4 5 6
10 20 30 40 50 60];
result = mat ./ mat(2,:)
which will output :
result =
100 100 100 100 100 100
1 1 1 1 1 1
10 10 10 10 10 10
This will work in Octave and Matlab since R2016b.