【问题标题】:Average every N rows by column按列平均每 N 行
【发布时间】:2019-12-06 13:52:52
【问题描述】:

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

例如:

myMatrix = randi(240,30)

这就是我目前所拥有的:

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

这似乎有效,但我认为它只适用于第一列。 如何将其扩展到每列?

【问题讨论】:

    标签: matlab matrix average


    【解决方案1】:

    您可以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
    

    多维度的reshape()简介。

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

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

    这是一个四列矩阵。现在,如果我们将其重塑为 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
    

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-29
        • 2015-08-01
        相关资源
        最近更新 更多