Question

Is there a function in MATLAB which allows to aggregate (or we can say sum) columns in a matrix per defined number of columns?

For example I have:

A =

 1     2     3     4     5     6
 9    10    11    12    13    14
17    18    19    20    21    22

I wish to aggregate every 2 columns, like this: col1+col2, and then col3+col4, and then col5+col6, so my output is:

A_agg =

 3     7    11
19    23    27
35    39    43

I couldn't find a built-in function and was trying to write a for loop but I couldn't manage to do it since I am quite new to programming. Do you have any suggestions/solutions how this could be solved with a for loop, or maybe there is a built-in function?

Was it helpful?

Solution 2

You can use a combination of mat2cell and cellfun. You can use mat2cell to split up your matrices into individual 2 column chunks. Each chunk would be stored as a cell in a cell array. You can then use cellfun to take each cell and sum row-wise. After you're done, you can use cell2mat to convert back.

Using your example:

A = [1:6;9:14;17:22];
B = mat2cell(A, 3, [2 2 2]);
C = cellfun(@(x) sum(x,2), B, 'UniformOutput', false);
A_agg = cell2mat(C);

A_agg should thus give you:

A_agg =

 3     7    11
19    23    27
35    39    43

Let's walk through the code slowly:

A is defined as we had before. B will be a cell array, and will segment your matrix into matrices of 2 columns per cell. The first parameter is the matrix you want to decompose (in our case A). The second parameter tells you how many rows each segment should have. Because we want all of the matrices to have the same number of rows, we thus supply one number which is 3. After, you specify the number of columns you want per matrix. Because there are 6 columns, we need 3 matrices, and so you'd specify a vector of [2 2 2].

C is the output of cellfun, where cellfun applies a function to every single element in a cell matrix. What you want to do here is for each cell (essentially each matrix), you want to sum row-wise. The first parameter is an anonymous function that takes in a matrix from each cell, and sums row-wise. The second parameter is the cell array we just created. You'll notice that we have an additional flag to set: UniformOutput. The reason why you have to set UniformOutput = false is because if you apply cellfun without that flag, the expected result at the end of the function you apply to each cell is scalar. Because we are outputting a column vector instead, we have to set this flag to false.

A_agg will thus aggregate all of your cells back to matrix form.

If you want to do this for any size matrix, bear in mind that there has to be an even amount of columns for this work. What I mean by even is that the number of columns has to be evenly divisible by 2. You would thus re-run the code like so:

B = mat2cell(A, size(A,1), 2*ones(1, size(A,2)/2));
C = cellfun(@(x) sum(x,2), B, 'UniformOutput', false);
A_agg = cell2mat(C);

OTHER TIPS

Since sum operates down columns in a matrix, I first reshape A so that it has 2 rows and 9 columns, then sum down each column. Then reshape back to the desired output matrix A_agg.

A=[1  2  3  4  5  6
   9  10 11 12 13 14 
   17 18 19 20 21 22]

[m,n]=size(A);
A_agg=reshape(sum(reshape(A',2,[])),m,[])'

Another possibility, if you have the Image Processing Toolbox, is to use blockproc. Let n denote the number of columns to be aggregated (2 in your example). Then:

A_agg = blockproc(A, [size(A,1) n], @(x) sum(x.data, 2));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top