按列平均每 N 行

Glu*_*Glu 4 matlab average matrix

我有四个 240x30 的矩阵。我需要计算每 15 行的平均值,我需要按列计算。所以,最后我应该有 30 列有 16 个值。

因此,例如:

myMatrix = randi(240,30)
Run Code Online (Sandbox Code Playgroud)

这就是我到目前为止所拥有的:

averageBins = 15;
meanByBinsMyMatrix = arrayfun(@(i) mean(myMatrix (i:i+averageBins-1)),1:averageBins:length(myMatrix )-averageBins+1)'; % the averaged vectormean()
Run Code Online (Sandbox Code Playgroud)

这似乎有效,但我认为它只对第一列起作用。如何扩展它以在每一列上工作?

Adr*_*aan 7

您可以reshape()将第一维从 a 到 15×n 矩阵,将列保留为第三维。然后取第一个维度的平均值,即你的n行块。由于这将1x16x30在您的情况下产生一个矩阵,squeeze()因此最后一个维度。

n = 15;
A = rand(240,30);
B = reshape(A,[n, size(A,1)/n, size(A,2)]); %crashes for size(A,1)/n != integer
C = squeeze(mean(B,1)); % Calculate the mean over the first dimension
Run Code Online (Sandbox Code Playgroud)

reshape()多维度的简短介绍。

创建一个小矩阵,例如magic(4),用于可视化:

A = magic(4)
A =
    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1
Run Code Online (Sandbox Code Playgroud)

这是一个四列矩阵。现在,如果我们将其重塑为 2x2x4 矩阵,那么我们的维度去哪里了?让我们试试看:

B = reshape(A,[2,2,4])
B(:,:,1) =
    16     9
     5     4
B(:,:,2) =
     2     7
    11    14
B(:,:,3) =
     3     6
    10    15
B(:,:,4) =
    13    12
     8     1
Run Code Online (Sandbox Code Playgroud)

发生了什么?的第一列Acontains [16;5;9;4]。第一个“页面”,也就是第三维的第一个条目,B正好包含这些数字!

reshape()工作,这意味着它“遍历”初始矩阵(1,1)->(2,1)->(3,1)等,直到到达第一列的末尾。然后它从 (1,2)->(2,2)->(3,2) 等开始读取。
至于存储部分:MATLAB 以相同的顺序存储它们,因此按列存储。当它填满一个维度时,它会将下一个维度索引增加1并继续填充。因此,1x4 的第一列A被存储为[16;5]第一列,然后第二列被填充,使得第一页为B(:,:,1) = [16 9;5 4],即它开始填充第一页的第二列。现在第一页已满,第二列A被放入第二页B以同样的方式,第三列转到第三页,依此类推,直到A复制所有元素。

注意:这就是为什么“大小”参数reshape如此重要的原因,它告诉程序何时开始下一个维度。您的尺寸的乘积,即元素数量,在此操作期间不能更改!

在原始情况下执行此操作后,您最终会得到一个 15×16×30 的矩阵。这意味着您有 30 页,原始列,每列 16 列,块数,15 行,即每组中的元素数。
然后mean(B,1)告诉mean第一个维度取平均值,即每个块中的元素,以及所有块和页面中的元素。

剩下的唯一小事是 MATLAB 默认不会去除非尾随单例维度,因此您最终会得到一个 1×16×30 矩阵。squeeze(),最后,去掉所有的单一维度,留下一个 16×30 的矩阵,其中包含相应行/列位置中每个包含 15 个元素的块的平均值。


Lui*_*ndo 5

您可以使用splitapply来计算每组行的平均值。即使行数不是组大小的倍数(最后一组行数较少),这也有效:

result = splitapply(@(x)mean(x,1), myMatrix, floor((0:size(myMatrix,1)-1)/averageBins).'+1);
Run Code Online (Sandbox Code Playgroud)