Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum every n rows of matrix

Is there any way that I can sum up columns values for each group of three rows in a matrix?
I can sum three rows up in a manual way.

For example

% matrix is the one I wanna store the new data.
% data is the original dataset.
matrix(1,1:end) = sum(data(1:3, 1:end))
matrix(2,1:end) = sum(data(4:6, 1:end))
...

But if the dataset is huge, this wouldn't work.
Is there any way to do this automatically without loops?

like image 494
Chris Su Avatar asked Jan 12 '23 09:01

Chris Su


2 Answers

Here are four other ways:

  1. The obligatory for-loop:

    % for-loop over each three rows
    matrix = zeros(size(data,1)/3, size(data,2));
    counter = 1;
    for i=1:3:size(data,1)
        matrix(counter,:) = sum(data(i:i+3-1,:));
        counter = counter + 1;
    end
    
  2. Using mat2cell for tiling:

    % divide each three rows into a cell
    matrix = mat2cell(data, ones(1,size(data,1)/3)*3);
    
    % compute the sum of rows in each cell
    matrix = cell2mat(cellfun(@sum, matrix, 'UniformOutput',false));
    
  3. Using third dimension (based on this):

    % put each three row into a separate 3rd dimension slice
    matrix = permute(reshape(data', [], 3, size(data,1)/3), [2 1 3]);
    
    % sum rows, and put back together
    matrix = permute(sum(matrix), [3 2 1]);
    
  4. Using accumarray:

    % build array of group indices [1,1,1,2,2,2,3,3,3,...]
    idx = floor(((1:size(data,1))' - 1)/3) + 1;
    
    % use it to accumulate rows (appliead to each column separately)
    matrix = cell2mat(arrayfun(@(i)accumarray(idx,data(:,i)), 1:size(data,2), ...
        'UniformOutput',false));
    

Of course all the solution so far assume that the number of rows is evenly divisble by 3.

like image 141
Amro Avatar answered Jan 17 '23 19:01

Amro


This one-liner reshapes so that all the values needed for a particular cell are in a column, does the sum, and then reshapes the back to the expected shape.

reshape(sum(reshape(data, 3, [])), [], size(data, 2))

The naked 3 could be changed if you want to sum a different number of rows together. It's on you to make sure the number of rows in each group divides evenly.

like image 45
Prashant Kumar Avatar answered Jan 17 '23 21:01

Prashant Kumar