我有一个非常大的矩阵(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
答案 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_avg
中M
中给定元素中的哪个元素有贡献,然后使用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);