矩阵每n行求和

4

有没有办法在矩阵中为每个三行分组汇总列值?
我可以手动地将三行相加。

例如:

% 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))
...

但如果数据集非常大,这样做就行不通了。
有没有办法自动完成这个过程而不需要循环呢?


可能是重复的问题:计算特定间隔内的总和 - bla
对我来说看起来不像是重复项,因为我不清楚一个简单的reshape是否足以解决问题。 - Prashant Kumar
我不同意,只需要一个reshape然后sum和squeeze就可以了。唯一的区别是这个问题是2D而不是1D。以下是解决方案:squeeze(sum(reshape(a,size(a,2), 3,[]))) - bla
但仅仅因为Amro的回答,这个问题就值得了... +1 Amro - bla
4个回答

5

以下是另外四种方法:

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

当然,到目前为止,所有的解决方案都假设行数可以被 3 整除。


这些答案非常有帮助。它们每一个都是学习的好例子。非常感谢。@Amro - Chris Su
实际上,我注意到还有另一个问题。如果行数不能被整除怎么办?不知道该如何解决。我只是删除一些数据使得行数能够被整除。你有经验的想法吗?Amro? - Chris Su
@ChrisSu:我添加了第四个解决方案:一个简单的for循环。你不应该那么快地抛弃它,它也相对较快(感谢MATLAB中的JIT编译)。 - Amro
@ChrisSu:在这种情况下,只需像以前一样处理 data(1:3*N,:),其中 N = floor(size(data,1)/3),然后添加剩余的任何内容(剩余一行或两行的总和)。当然,所有这些解决方案都可以推广到与任何 X 行的组合一起使用(我们上面的例子中 X=3)。 - Amro
第四个解决方案很好。循环是可以的,但它仍然是C或Java编程思维。由于我对Matlab还很陌生,我想训练自己更好地理解本质。关于不可分割的问题,我认为你是正确的。预先计算N可能比我的解决方案更好。感谢您详细的答复。 - Chris Su

4
这个一行代码会将所有需要用于特定单元格的值转换为列,计算它们的总和,然后再将其重新转换为预期形状。
reshape(sum(reshape(data, 3, [])), [], size(data, 2))

裸露的 3 可以更改,如果你想把不同数量的行相加。你需要确保每个组中的行数可以均分。

哇~这个真的很酷。它运行得很好!Matlab太棒了!非常感谢。@Prashant - Chris Su

0

将矩阵切成三块并将它们相加:

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

如果size(data,1)不是3的倍数,就会出现错误,因为三个部分的大小不同。如果适用于您的数据,可以通过截断data或在末尾添加一些零来解决这个问题。

您还可以使用reshape和3D数组来实现一些高级操作。但是,除非您需要将3替换为变量,否则我更喜欢上述方法...)


是的,我明白你的意思。如果所需的部件很少,这种方法是可行的。实际上,它可能会增长到140个部件。在那种情况下,这种方式就不适用了。有更好的想法吗? - Chris Su

0

Prashant之前回答得很好,但我想做一个简单的修改:

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

有一个",1"使得该语句在fl==1(原始值)时仍然运行。 我是通过以下方式在for循环中运行它时发现的:

... 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接