inverse reshape in matlab - matlab

I have used the function reshape() to help change sizes from a 3D matrix to a 2D one. Eg :
a = [1 2; 3 4];
b = [5 6; 7 8];
c = cat(3,a,b);
Here c is the matrix with 3 dimensions. I used reshape to change it thus:
[n,m,d] = size(c);
d = reshape(c, [n*m , d]);
The size of d is 4x2.
After this operation, how do I get back c from d? What I would like to know is the inverse of the reshape function.
Thank you.

Slightly modifying your notations (you have 2 d):
a = [1 2; 3 4];
b = [5 6; 7 8];
c = cat(3,a,b);
[n,m,d] = size(c);
dd = reshape(c, [n*m , d]);
cc = reshape(dd, [n, m , d]);
and you can check that cc is equal to c.

I think the problem is you overwrote the depth of the array d to be the reshaped array. Try:
[n,m,p] = size(c);
d = reshape(c, [n*m , p]);
reshape(d,[n m p])
Result:
ans(:,:,1) =
1 2
3 4
ans(:,:,2) =
5 6
7 8

Related

MATLAB: Forming an array of matrices and do operations with respect to each matrix "element"

I have an array of matrix m such that
m1 = [1 2;3 4];
m2 = [2 7; 8 9];
m3 = [9 7; 8 91];
m = [m1 m2 m3]
m =
1 2 2 7 9 7
3 4 8 9 8 91
I also have a vector
v = [1 2 3];
such that i want the operations between v and m result in h such that
h = [1*m1 2*m2 3*m3] = [h1 h2 h3];
I imagine I have to do this in 3-dimensional array for h, which is a 3d array. Or maybe there are better ways.
Let A be a simple 2 by 2 matrix, rand(2,2).
From h i want to extract h1 h2 and h3 out(or better not doing any extraction) and perform operations to A such that
1.
h1*A*h1'
h2*A*h2'
h3*A*h3'
and
2.
h1*h1', h2*h2', h3*h3'.
Why i want to do this in array is because i have a lot of matrix mi so I want to avoid for loop by vectorization.
From what i could understand from the question, i suppose element-wise multiplication would be better choice. You would just have to use proper concatenation and repeatation of matrices.
m1 = [1 2; 3 4];
m2 = [2 7; 8 9];
m3 = [9 7; 8 91];
% Concatenate to create 3D matrix
m = cat(3,m1,m2,m3);
v = [1 2 3];
% Create similar 3D matrix
v1 = cat(3,ones(size(m1))*v(1),ones(size(m2))*v(2),ones(size(m3))*v(3));
% Simple element wise multiplication
h = m.*v1;
% Creating a repeated 3D matrix A, repetation is along third dimension
A = repmat(rand(2,2),[1 1 3]);
% Outputs
op_1 = h.*A.*permute(h,[2 1 3]);
op_2 = h.*permute(h,[2 1 3]);

Design a simple matrix to group values from matrices

This problem is a succession of my previous problem:
1) Extract submatrices, 2) vectorize and then 3) put back
Now, I have two patients, named Ann and Ben.
Indeed the matrices A and B are data for Ann and the matrix C is data for Ben:
Now, I need to design a matrix M such that y = M*x where
y = [a11, a21, a12, a22, b11, b21, b12, b22]' which is a vector, resulting from concatenation of the top-left sub-matrices, Ann and Ben;
x = [2, 5, 4, 6, 7, 9, 6, 2, 9, 3, 4, 2]' which is a vector, resulting from concatenation of sub-matrices A, B and C.
Here, the M is a 8 by 12 matrix that
a11 = 2 + 7, a21 = 5 + 9, .., a22 = 6 + 2 and b11 = 9, ..b22 = 2.
I design the M manually by:
M=zeros(8,12)
M(1,1)=1; M(1,5)=1; % compute a11
M(2,2)=1; M(2,6)=1; % compute a21
M(3,3)=1; M(3,7)=1; % compute a12
M(4,4)=1; M(4,8)=1; % compute a22
M(5,9)=1; % for setting b11 = 9, C(1,1)
M(6,10)=1; % for setting b21 = 3, C(2,1)
M(7,11)=1; % for setting b12 = 4, C(1,2)
M(8,12)=1 % for setting b22 = 2, C(2,2)
Obviously, in general for M(i,j), i means the 8 linear-index position of vector y and j means linear-index position of vector x.
However, I largely simplified my original problem that I want to construct this M automatically.
Thanks in advance for giving me a hand.
Here you have my solution. I have essentially build the matrix M automatically (from the proper indexes) as you suggested.
A = [2 4 8;
5 6 3;
10 3 6];
B = [7 6 3;
9 2 9;
10 2 3];
C = [9 4 7;
3 2 5;
10 3 4];
% All matrices in the same array
concat = cat(3, A, B, C);
concat_sub = concat(1:2,1:2,:);
x = concat_sub(:);
n = numel(x)/3; %Number of elements in each subset
M2 = zeros(12,8); %Transpose of the M matrix (it could be implemented directly over M but that was my first approach)
% The indexes you need
idx1 = 1:13:12*n; % Indeces for A
idx2 = 5:13:12*2*n; % Indices for B and C
M2([idx1 idx2]) = 1;
M = M2';
y = M*x
I have taken advantage of the shape that the matrix M shold take:
You can index into things and extract what you want without multiplication. For your example:
A = [2 4 8; 5 6 3; 10 3 6];
B = [7 6 3; 9 2 9; 10 2 3];
C = [9 4 7;3 2 5; 10 3 4];
idx = logical([1 1 0;1 1 0; 0 0 0]);
Ai = A(idx);
Bi = B(idx);
Ci = C(idx);
output = [Ai; Bi; Ci];
y = [Ai + Bi; Ci]; % desired y vector
This shows each step individually but they can be done in 2 lines. Define the index and then apply it.
idx = logical([1 1 0;1 1 0;0 0 0]);
output = [A(idx); B(idx); C(idx)];
y = [Ai + Bi; Ci]; % desired y vector
Also you can use linear indexing with idx = [1 2 4 5]' This will produce the same subvector for each of A B C. Either way works.
idx = [1 2 4 5]';
or alternatively
idx = [1;2;4;5];
output = [A(idx); B(idx); C(idx)];
y = [Ai + Bi; Ci]; % desired y vector
Either way works. Check out doc sub2ind for some examples of indexing from MathWorks.

Get elements of vector by non-given indexes in Matlab

I have the following:
a = [1:10 1:10];
idx = [3 5 7];
b = a(idx);
b = [3 5 7];
c = a(~idx); %this syntax is not correct!
c = [1 2 4 6 8 9 10 1 2 3 4 5 6 7 8 9 10];
is there a straight forward way to get c like this? In other words I have an vector and I want to exclude the elements at the given indexes, how can I do that?
Explicit way: generate a negated logical index:
logical_idx = true(1,numel(a));
logical_idx(idx) = false;
c = a(logical_idx);
More compact code using setdiff or ismember:
c = a(setdiff(1:numel(a), idx));
or
c = a(~ismember(1:numel(a), idx));
Directly remove elements indexed by idx:
c = a;
c(idx) = [];

Extracting a specific element from each cell within cell array

I have a cell array A of size 10x10 (say). Each cell in turn contains a 5x20 matrix. I want to select (i,j) element from each cell, where (i,j) are indices within a loop. I can run 4 for loops and easily get the answer. It may even be faster as it has been discussed many times that loops could be faster than cellfun, structfun etc.
Still, is there any solution using cellfun which I can use in a loop over (i,j) and extract (i,j) element in each cell? I tried writing a function which will act as handle to cellfun but I couldn't access two-leves down i.e. A{eachCellRow,eachCellCol}(i,j).
Example:
If A={[1 2;5 6], [3 4; 6 7]; [3 4; 6 7], [9 8; 5 6]};
Then for i=1, j=1 and i=2, j=1 output should be:
B=[1 3; 3 9] and B=[5 6; 6 5]
CELL2MAT gets all the data from a cell array that consists of numeric data only, into a numeric array. So, that helped us here. For your original problem, try this -
celldim_i = 10;
celldim_j = 10;
block_size_i = 5;
block_size_j = 20;
search_i = i; %// Edit to your i
search_j = j; %// Edit to your j
A_mat = cell2mat(A);
out = A_mat(search_i+block_size_i*(0:celldim_i-1),search_j+block_size_j*(0:celldim_j-1))
The easy to use cellfun one-liner would be:
ii = 2;
jj = 1;
A = {[1 2;5 6], [3 4; 6 7]; [3 4; 6 7], [9 8; 5 6]};
B = cell2mat( cellfun( #(x) x(ii,jj), A, 'uni', 0) )
gives:
B =
5 6
6 5
Advantage over Divakar's Solution: it works also for inconsistent matrix sizes in A.
And if you want to avoid also the outer loop, another fancy two-liner:
dim = [2 2];
[II, JJ] = meshgrid( 1:dim(1), 1:dim(2) );
C = cellfun( #(y) ...
{ cell2mat( cellfun( #(x) x( real(y), imag(y) ), A, 'uni', 0) ) },...
num2cell( II(:)+1i*JJ(:) ))
gives:
>> celldisp(C)
C{1} = % ii = 1 , jj = 1
1 3
3 9
C{2} = % ii = 1 , jj = 2
2 4
4 8
C{3} = % ii = 2 , jj = 1
5 6
6 5
C{4} = % ii = 2 , jj = 2
6 7
7 6
If memory is not an issue, you can concat all matrices along a third dim; and then indexing is very easy:
%// Example data
A = {[1 2;5 6], [3 4; 6 7]; [3 4; 6 7], [9 8; 5 6]};
ii = 2;
jj = 1;
%// Compute the result B
A2 = cat(3,A{:}); %// concat along third dim
B = reshape(A2(ii,jj,:),size(A{1})); %// index A2 and reshape

Reshape 3d matrix in z direction

we have a = [1 2; 3 4]; and b = [5 6;7 8]; and z = cat(3,a,b). I want to vectorize the 3d matrix so the reresult would be c = [1 5; 2 6; 3 7; 4 8 ]? I know it is related to reshape but I can not find the way:)
Thanks.
If you need to go via z:
c = reshape(permute(z,[2 1 3]),[],2)
Otherwise,
c = [reshape(a',[],1),reshape(b',[],1)];
reshape(permute(z,[2 1 3]), 4, 2)