AnnaSchumann
AnnaSchumann

Reputation: 1271

Collapsing matrix into columns

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.

Upvotes: 6

Views: 549

Answers (8)

Robert Seifert
Robert Seifert

Reputation: 25232

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

out = im2col(A,[1 4], 'distinct').'

Upvotes: 0

Rody Oldenhuis
Rody Oldenhuis

Reputation: 38042

Shameless steal from @Divakar:

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

Upvotes: 4

Rafael Monteiro
Rafael Monteiro

Reputation: 4549

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]);

Upvotes: 1

Rody Oldenhuis
Rody Oldenhuis

Reputation: 38042

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.

Upvotes: 0

marcoresk
marcoresk

Reputation: 1965

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

Upvotes: -2

Novice_Developer
Novice_Developer

Reputation: 1492

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

Upvotes: 1

Patrick
Patrick

Reputation: 36

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

Upvotes: 2

StefanM
StefanM

Reputation: 781

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];

Upvotes: 2

Related Questions