2014-05-13 65 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));