我应该如何平均矩阵中的行组来生成一个新的更小的矩阵?

时间:2012-03-06 01:29:20

标签: matlab

我有一个非常大的矩阵(216行,31286列)的双打。由于特定于数据的原因,我想平均每9行产生一个新行。因此,新矩阵将有216/9 = 24行。

我是一名Matlab初学者,所以我想知道我想出的这个解决方案是否可以改进。基本上,它遍历每个组,总结行,然后将新行除以9.这是我写的简化版本:

matrix_avg = []
for group = 1:216/9
    new_row = zeros(1, 31286);
    idx_low = (group - 1) * 9 + 1;
    idx_high = idx_low + 9 - 1;
    % Add the 9 rows to new_row
    for j = idx_low:idx_high
        new_row = new_row + M(j,:);
    end
    % Compute the mean
    new_row = new_row ./ 9
    matrix_avg = [matrix_avg; new_row];
end

3 个答案:

答案 0 :(得分:8)

你可以reshape你的大矩阵从216 x 31286到9 x(216/9 * 31286)。

然后您可以使用mean,它对每列进行操作。由于您的矩阵每列只有9行,因此需要9行平均值。

然后你可以reshape你的矩阵。

% generate big matrix
M = rand([216 31286]);
n = 9   % want 9-row average.

% reshape
tmp = reshape(M, [n prod(size(M))/n]);
% mean column-wise (and only 9 rows per col)
tmp = mean(tmp);
% reshape back
matrix_avg = reshape(tmp, [ size(M,1)/n size(M,2) ]);

在单行中(但你为什么会这样?):

matrix_avg = reshape(mean(reshape(M,[n prod(size(M))/n])), [size(M,1)/n size(M,2)]);

注意 - 如果M中的行数不能完全被9整除,则会出现问题,但原始代码也是如此。

答案 1 :(得分:1)

我测量了4种解决方案,结果如下:

reshape: Elapsed time is 0.017242 seconds.
blockproc [9 31286]: Elapsed time is 0.242044 seconds.
blockproc [9 1]: Elapsed time is 44.477094 seconds.
accumarray: Elapsed time is 103.274071 seconds.

这是我使用的代码:

M = rand(216,31286);

fprintf('reshape: ');
tic;
n = 9;
matrix_avg1 = reshape(mean(reshape(M,[n prod(size(M))/n])), [size(M,1)/n size(M,2)]);
toc

fprintf('blockproc [9 31286]: ');
tic;
fun = @(block_struct) mean(block_struct.data);
matrix_avg2 = blockproc(M,[9 31286],fun);
toc

fprintf('blockproc [9 1]: ');
tic;
fun = @(block_struct) mean(block_struct.data);
matrix_avg3 = blockproc(M,[9 1],fun);
toc

fprintf('accumarray: ');
tic;
[nR,nC] = size(M);
n2average = 9;
[xx,yy] = ndgrid(1:nR,1:nC);
x = ceil(xx/n2average); %# makes xx 1 1 1 1 2 2 2 2 etc
matrix_avg4 = accumarray([xx(:),yy(:)],M(:),[],@mean);
toc

答案 2 :(得分:0)

这是基于accumarray的替代方案。您创建一个包含行{列}索引的数组到matrix_avg,告诉您matrix_avgM中给定元素中的哪个元素有贡献,然后使用accumarray来平均元素这有助于matrix_avg中的相同元素。即使M中的行数不能被9整除,此解决方案仍然有效。

M = rand(216,31286);
[nR,nC] = size(M);
n2average = 9;

[xx,yy] = ndgrid(1:nR,1:nC);
x = ceil(xx/n2average); %# makes xx 1 1 1 1 2 2 2 2 etc

matrix_avg = accumarray([xx(:),yy(:)],M(:),[],@mean);