Sum every n rows of the matrix

Is there a way that I can sum the column values ​​for each group of three rows in a matrix?
I can sum three lines in manual mode.

for instance

% 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 data set is huge, it will not work.
Is there a way to do this automatically without loops?

+4
source share
4 answers

This single-line reshape so that all the values ​​needed for a particular cell are in the column, does sum and then reshape back to the expected form.

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

Naked 3 can be changed if you want to summarize a different number of lines. You need to make sure that the number of rows in each group is evenly distributed.

+3
source

Here are four more ways:

  • Mandatory 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 
  • Using mat2cell to breakdown:

     % 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)); 
  • Using the 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]); 
  • 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 solutions still assume that the number of rows is evenly divided by 3 .

+5
source

Draw a matrix into three parts and add them together:

 matrix = data(1:3:end, :) + data(2:3:end, :) + data(3:3:end, :); 

This will give an error if size(data,1) not a multiple of three, since the three parts will not be the same size. If this matches your data, you can work around this by trimming data or adding some zeros to the end.

You can also do something unusual with reshape and 3D arrays. But I would prefer the above (unless you need to replace 3 with a variable ...)

0
source

Prashant answered well, but I would have a simple correction:

 fl = filterLength; A = yourVector (where mod(A,fl)==0) sum(reshape(A,fl,[]),1).'/fl; 

There is a ", 1" that makes the string work even with fl == 1 (the original values). I found this when running in a for loop like this:

 ... read A ... % Plot data hold on; averageFactors = [1 3 10 30 100 300 1000]; colors = hsv(length(averageFactors)); clear legendTxt; for i=1:length(averageFactors) % ------ FILTERING ---------- clear Atrunc; clear ttrunc; clear B; fl = averageFactors(i); % filter length Atrunc = A(1:L-mod(L,fl),:); ttrunc = t(1:L-mod(L,fl),:); B = sum(reshape(Atrunc,fl,[]),1).'/fl; tB = sum(reshape(ttrunc,fl,[]),1).'/fl; length(B) plot(tB,B,'color',colors(i,:) ) %kbhit () endfor 
0
source

Source: https://habr.com/ru/post/1502136/


All Articles