【问题标题】:Matlab column aggregationMatlab 列聚合
【发布时间】:2014-05-13 23:39:35
【问题描述】:

MATLAB 中是否有一个函数允许按照定义的列数聚合(或者我们可以说求和)矩阵中的列?

例如我有:

A =

 1     2     3     4     5     6
 9    10    11    12    13    14
17    18    19    20    21    22

我希望每 2 列聚合一次,像这样:col1+col2,然后是 col3+col4,然后是 col5+col6,所以我的输出是:

A_agg =

 3     7    11
19    23    27
35    39    43

我找不到内置函数,并试图编写一个for 循环,但我无法做到,因为我对编程很陌生。您是否有任何建议/解决方案如何使用for 循环来解决这个问题,或者可能有一个内置函数?

【问题讨论】:

    标签: matlab for-loop aggregation


    【解决方案1】:

    由于sum 对矩阵中的列进行向下操作,因此我首先对A 进行整形,使其具有 2 行和 9 列,然后对每一列求和。然后重塑回所需的输出矩阵A_agg

    A=[1  2  3  4  5  6
       9  10 11 12 13 14 
       17 18 19 20 21 22]
    
    [m,n]=size(A);
    A_agg=reshape(sum(reshape(A',2,[])),m,[])'
    

    【讨论】:

    • reshape 做得很好。从来没有想过以这种方式reshape! +1
    • @David 感谢这个简单而有效的解决方案,它对我来说非常有效!
    • 这可能比使用cellfun 更快。 +1
    • @LuisMendo:我同意。我看不到如何使用reshape 来做到这一点,所以我默认将矩阵分割成单元格并单独处理每个单元格。这就是 SO 的优点。你教别人一些东西,你也一路学习新的技巧!
    【解决方案2】:

    您可以使用mat2cellcellfun 的组合。您可以使用 mat2cell 将矩阵拆分为单独的 2 列块。每个块将作为一个单元存储在一个单元数组中。然后,您可以使用 cellfun 获取每个单元格并逐行求和。完成后,您可以使用cell2mat 转换回来。

    使用您的示例:

    A = [1:6;9:14;17:22];
    B = mat2cell(A, 3, [2 2 2]);
    C = cellfun(@(x) sum(x,2), B, 'UniformOutput', false);
    A_agg = cell2mat(C);
    

    A_agg 因此应该给你:

    A_agg =
    
     3     7    11
    19    23    27
    35    39    43
    

    让我们慢慢看代码:

    A 的定义与我们之前的定义相同。 B 将是一个单元格数组,并将您的矩阵分割成每个单元格 2 列的矩阵。第一个参数是您要分解的矩阵(在我们的例子中为A)。第二个参数告诉您每个段应该有多少行。因为我们希望所有矩阵都具有相同的行数,所以我们提供一个数字,即3。之后,您指定每个矩阵所需的列数。因为有 6 列,我们需要 3 个矩阵,因此您需要指定一个向量 [2 2 2]

    Ccellfun 的输出,其中cellfun 将函数应用于单元矩阵中的每个元素。您在这里要做的是对于每个单元格(基本上是每个矩阵),您想要逐行求和。第一个参数是一个匿名函数,它从每个单元格中获取一个矩阵,并逐行求和。第二个参数是我们刚刚创建的元胞数组。你会注意到我们有一个额外的标志要设置:UniformOutput。您必须设置 UniformOutput = false 的原因是,如果您在没有该标志的情况下应用 cellfun,则应用到每个单元格的函数末尾的预期结果是标量。因为我们输出的是列向量,所以我们必须将此标志设置为 false。

    A_agg 将因此将所有单元格聚合回矩阵形式。

    如果您想对任何大小的矩阵执行此操作,请记住,此工作的列数必须是偶数。我所说的偶数是指列数必须能被 2 整除。因此,您可以像这样重新运行代码:

    B = mat2cell(A, size(A,1), 2*ones(1, size(A,2)/2));
    C = cellfun(@(x) sum(x,2), B, 'UniformOutput', false);
    A_agg = cell2mat(C);
    

    【讨论】:

    • 非常感谢!这个例子对我来说效果很好,出于某种原因我不得不添加:C = cellfun(@(x) sum(x,2), B, 'UniformOutput',false); 唯一的问题是我有一个 1750x250 的矩阵,我想将其调整为 1750x50,但它甚至不存在奇数矩阵的任何解决方案?
    • 哦,是的。我忘记了。让我将其添加到我的代码中。至于你的调整大小,我不太确定我是否遵循。使用我拥有的代码,它会将您的矩阵减少到 1750 x 125。为什么需要它为 50?您想对每 五个 列进行聚合吗?如果你这样做,这是一个非常容易解决的问题。只需将B 更改为:B = mat2cell(A, size(A,1), 5*ones(1, size(A,2)/5));
    • FWIW:您必须添加 UniformOutput = false 的原因是因为如果您在没有该标志的情况下应用 cellfun,则应用到它的函数末尾的预期结果是标量。因为我们输出的是 列向量,所以我们必须将此标志设置为 false。我会编辑我的帖子。好地方!
    • 对不起,我误解了你之前写的关于偶数列的内容。我现在运行您的代码,它对我来说非常有效!非常感谢!
    • 另外,如果对您有帮助,请考虑接受我们的答案之一。
    【解决方案3】:

    如果您有图像处理工具箱,另一种可能性是使用blockproc。让n 表示要聚合的列数(在您的示例中为2)。那么:

    A_agg = blockproc(A, [size(A,1) n], @(x) sum(x.data, 2));
    

    【讨论】:

      猜你喜欢
      • 2012-06-15
      • 2023-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多