2014-05-13 67 views
0

在MATLAB中是否有一个函数允许根据定义的列数聚合(或我们可以说sum)列中的矩阵?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循环来解决这个问题,或者有一个内置函数?

回答

0

您可以使用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); 
+0

非常感谢!这个例子对我来说效果很好,出于某种原因,我必须加上:'C = cellfun(@(x)sum(x,2),B'UniformOutput',false);唯一的问题是我有一个矩阵是1750x250,我想调整它的大小到1750x50,但它不是偶数,奇数矩阵有没有解决方案? – vaitas

+0

OH是的。我忘了那个。让我将其添加到我的代码中。至于你的调整大小,我不太确定我是否遵循。使用我的代码,它会将您的矩阵减少到1750 x 125.您为什么需要它是50?你想聚集每个** 5列吗?如果你这样做,那是一个非常简单的解决方法。只需将'B'改为:'B = mat2cell(A,size(A,1),5 * ones(1,size(A,2)/ 5));' – rayryeng

+0

FWIW:你必须添加'UniformOutput = false'是因为如果你应用没有该标志的'cellfun',你应用到它的函数结尾的预期结果是标量。因为我们正在输出**列向量**,所以我们必须将此标志设置为false。我将编辑我的帖子。好地方! – rayryeng

4

由于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,[])' 
+0

“重塑”的好工作。从未想过以这种方式“重塑”它! +1 – rayryeng

+0

@David感谢这个简单而有效的解决方案,它对我来说非常合适! – vaitas

+1

这可能比使用'cellfun'更快。 +1 –

0

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

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