How to reshape multiple dimensions with constraints

Viewed 135

I have been trying to achieve this behavior using reshape. I'm new to matlab so I've been struggling a bit.

I have a

3 x 2 x 5 matrix called A

And I would like to merge dimensions 1 through 5, excluding 4. When combining them I want to retain the columns within each row in order.

I know I can do something like

A = reshape(A, [12, 2, 1]) but my concerns are this may not retain the order of the columns within each row and it doesn't allow me to exclude a dimension.

Example:

(:,:,1) =

0.3168    3.1825
1.5841    1.5766
-0.7892    3.0073


(:,:,2) =

-0.2131    3.9708
2.9435    0.4964
-0.2131    2.5985

(:,:,3) =

0.5012    -3.5328
0.4551    2.1314
-1.5956    3.4161

(:,:,4) =

-0.12    -3.28
-0.51    -2.14
-1.56    -3.61


(:,:,5) =

6.5012    3.538
0.4551    0.314
-0.5956    0.411

Output, let's say of combining all dimension except the 4th one

0.3168    3.1825
1.5841    1.5766
-0.7892    3.0073
-0.2131    3.9708
2.9435    0.4964
-0.2131    2.5985
0.5012    -3.5328
0.4551    2.1314
-1.5956    3.4161
6.5012    3.538
0.4551    0.314
-0.5956    0.411
2 Answers

You can achieve what you want through clever use of reshape, as you mentioned, as well as indexing. In addition, you will need to use permute (which switches dimensions around), because you want to keep each 'slice' intact.

First off, it is good to know that you can exclude your 4th slice using indexing. Consider the following example:

A = randi(100,3,2,5)
idxdim3 = [1,2,3,5];     % Create an array of integers corresponding to the slices you want
B = A(:,:,idxdim3)       % Extract all the slices you want, discarding the 4th

This will leave you with an array of size [3 x 2 x 4] in this case. Next, you can try to use reshape, but you will encounter a problem. reshape works its way up the dimensions, columns being the first dimension, rows being the second, and 'slices' being the third. As you said, you want to keep the columns within each row in order, but reshape will alter those before it will commence work in the third dimension. So we need to make the second and third dimension switch place first using permute:

% Leave 1 as the first dimension, but switches dimensions 2 and 3 around:
C = permute(B,[1 3 2]);      

Now we can reshape to the appropriate size:

D = reshape(C,[12 2 1]);

Which should give you the result you are looking for. Of course, we can combine most of these statements into a single line, like so:

A = randi(100,3,2,5);  % Put your data here instead
idxdim3 = [1,2,3,5];
B = reshape( permute( A(:,:,idxdim3), [1 3 2]), 12, 2);

Note: if you will work with different-size A's in the future, you can let reshape calculate one of the dimensions if you specify the others. The following will also work:

B = reshape( permute( A(:,:,idxdim3), [1 3 2]), [], 2);

reshape will calculate the 12 for you.

Example output:

A(:,:,1) =
44    80
39    19
77    49
A(:,:,2) =
45    76
65    28
71    68
A(:,:,3) =
66    50
17    96
12    35
A(:,:,4) =
59    26
23    51
76    70
A(:,:,5) =
90    14
96    15
55    26

B =
44    80
39    19
77    49
45    76
65    28
71    68
66    50
17    96
12    35
90    14
96    15
55    26

You need to use a combination of permute and reshape:

% delete A[:,:,4]
B = A(:,:,[1:3,5])
% permute dimension 2 and 3, because you want to concatenate your array according to the 3nd dimension before the 2nd dimension.
C = permute(B,[1 3 2])
% Use reshape with the first parameter beeing '[]' so matlab will automatically compute the number of line needed, the number of column is fixed: it's 2 or size(B,2)
C = reshape(C,[],size(B,2))
Related