6

I have a 2D matrix where the № of columns is always a multiple of 3 (e.g. 250×27) - due to a repeating organisation of the results (A,B,C, A,B,C, A,B,C, and so forth). I wish to reshape this matrix to create a new matrix with 3 columns - each containing the aggregated data for each type (A,B,C) (e.g. 2250×3).

So in a matrix of 250×27, all the data in columns 1,4,7,10,13,16,19,22,25 would be merged to form the first column of the resulting reshaped matrix.

The second column in the resulting reshaped matrix would contain all the data from columns 2,5,8,11,14,17,20,23,26 - and so forth.

Is there a simple way to do this in MATLAB? I only know how to use reshape if the columns I wanted to merge were adjacent (1,2,3,4,5,6) rather than non-adjacent (1,4,7,10,13,16) etc.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
AnnaSchumann
  • 1,261
  • 10
  • 22

8 Answers8

4

Shameless steal from @Divakar:

B = reshape( permute( reshape(A,size(A,1),3,[]), [1,3,2]), [], 3 );
Community
  • 1
  • 1
Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
2

Let A be your matrix. You can save every third column in one matrix like: (Note that you don't have to save them as matrices separately but it makes this example easier to read).

A = rand(27); %as test
B = A(:,1:3:end);
C = A(:,2:3:end);
D = A(:,3:3:end);

Then you use reshape:

B = reshape(B,[],1);
C = reshape(C,[],1);
D = reshape(D,[],1);

And finally put it all together:

A = [B C D];
StefanM
  • 797
  • 1
  • 10
  • 17
  • I suppose it could be made more compact by skipping the middle block and using `B(:)` in the final block, but overall this seems like the right way to go. – Dennis Jaheruddin Nov 09 '16 at 12:15
2

You can just treat every set of columns as a single item and do three reshapes together. This should do the trick:

[save as "reshape3.m" file in your Matlab folder to call it as a function]

function out = reshape3(in)
    [~,C]=size(in); % determine number of columns
    if mod(C,3) ~=0 
        error('ERROR: Number of rows must be a multiple of 3')
    end

    R_out=numel(in)/3; % number of rows in output

    % Reshape columns 1,4,7 together as new column 1, column 2,5,8 as new col 2 and so on
    out=[reshape(in(:,1:3:end),R_out,1), ...
        reshape(in(:,2:3:end),R_out,1), ...
        reshape(in(:,3:3:end),R_out,1)];
end
Patrick
  • 36
  • 2
1

Lets suppose you have a 3x6 matrix A

A = [1 2 3 4 5 6;6 5 4 3 2 1;2 3 4 5 6 7]
A =

     1     2     3     4     5     6
     6     5     4     3     2     1
     2     3     4     5     6     7

you extract the size of the matrix

b =size(A)

and then extract each third column for a single row

c1 = A((1:b(1)),[1:3:b(2)])
c2 = A((1:b(1)),[2:3:b(2)])
c3 = A((1:b(1)),[3:3:b(2)])

and put them in one matrix

A_result = [c1(:) c2(:) c3(:)]

A_result =

     1     2     3
     6     5     4
     2     3     4
     4     5     6
     3     2     1
     5     6     7
Novice_Developer
  • 1,432
  • 2
  • 19
  • 33
1

My 2 cents:

nRows = size(matrix, 1);
nBlocks = size(matrix, 2) / 3;
matrix = reshape(matrix, [nRows 3 nBlocks]);
matrix = permute(matrix, [1 3 2]);
matrix = reshape(matrix, [nRows * nBlocks 1 3]);
matrix = reshape(matrix(:), [nRows * nBlocks 3]);
Rafael Monteiro
  • 4,509
  • 1
  • 16
  • 28
0

Here's my 2 minute take on it:

rv  = @(x) x(:);
ind = 1:3:size(A,2);
B   = [rv(A(:,ind)) rv(A(:,ind+1)) rv(A(:,ind+2))];

saves a few ugly reshapes, may be a bit slower though.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
0

If you have the Image Processing Toolbox, im2col is a very handy solution:

out = im2col(A,[1 4], 'distinct').'
Robert Seifert
  • 25,078
  • 11
  • 68
  • 113
-2

Try Matlab function mat2cell, I think this form is allowed.

X is the "start matrix"    
C = mat2cell(X, [n], [3, 3, 3]); %n is the number of rows, repeat "3" as many times as you nedd

%extract every matrix
C1 = C{1,1}; %first group of 3 columns
C2 = C{1,2}; %second group of 3 columns 
%repeat for all your groups

%join the matrix with vertcat
Cnew = vertcat(C1,C2,C3); %join as many matrix n-by-3 as you have
marcoresk
  • 1,837
  • 2
  • 17
  • 29
  • 2
    Will not work (most obvious hint is that C1==C2), also it is generally a bad idea to use cells to go from 1 matrix shape to another as this is quite inefficient. – Dennis Jaheruddin Nov 09 '16 at 12:13
  • @DennisJaheruddin C1 = C2 is obviously my fault in wrinting index (updated), and thank you. Why Matlab in-built function are considered quite inefficient? – marcoresk Nov 09 '16 at 12:33
  • inbuilt functions in general are fine. But cell is a much more versatile datatype than matrix. As such it should not be a surprise that usually it is more efficient to operate on the matrix, rather than converting it to a cell, operating on the cell, and converting it to a matrix. -- For small problems efficiency may not be a concern, but in that case I would still argue that it is best practice for code clarity, to stick to matrices unless there is a compelling reason not to. – Dennis Jaheruddin Nov 09 '16 at 12:36
  • @DennisJaheruddin thank you for complete and fast answer :) – marcoresk Nov 09 '16 at 12:38