2012-06-14 34 views
2

我有一個m×m的矩陣,我想轉換爲一個m×m的矩陣,每個m×m的塊包含對角線每行。如何向量化矩陣的行對角化

例如,如果輸入是:

[1 2; 3 4; 5 6] 

輸出應爲:

[1 0; 0 2; 3 0; 0 4; 5 0; 0 6] 

當然,我不想通過步驟自己與for組裝矩陣步驟循環。
有沒有一種矢量化和簡單的方法來實現這一目標?

回答

4

對於要做到這一點的矢量化方法,請將對角線元素的線性索引創建到結果矩陣中,然後直接進行賦值。

%# create some input data 
inArray = [10 11;12 13;14 15]; 

%# make the index array 
[nr,nc]=size(inArray); 

idxArray = reshape(1:nr*nc,nc,nr)'; 
idxArray = bsxfun(@plus,idxArray,0:nr*nc:nr*nc^2-1); 

%# create output 
out = zeros(nr*nc,nc); 
out(idxArray) = inArray(:); 

out = 

    10  0 
    0 11 
    12  0 
    0 13 
    14  0 
    0 15 
+0

你能解釋一下'bsxfun'的功能嗎? – ja72

+0

@ ja72:bsxfun自動擴展數組,以便您可以例如添加一個n×1的數組到一個n×m的數組。開頭的句柄(在這種情況下爲「@ plus」)告訴執行哪個操作。使用'repmat'更快,更方便。 – Jonas

+1

'bsxfun'岩石! – Shai

4

下面是一個簡單的向量化溶液,假設X被輸入矩陣:

Y = repmat(eye(size(X, 2)), size(X, 1), 1); 
Y(find(Y)) = X; 

另一種替代方法是使用sparse,這可以寫爲一個整齊的一行:

Y = full(sparse(1:numel(X), repmat(1:size(X, 2), 1, size(X, 1)), X')); 
+1

+1:這一定是被接受的解決辦法; 2d步驟是Octave矩陣索引的另一個驚人應用 – topchef

+1

該解決方案比使用bsxfun更可取,因爲它不需要函數傳遞,因此可以在本機代碼中更好地進行優化。另外,考慮讓Y稀疏。 – dspyz

+0

@dspyz'sparse'是一個很好的建議,謝謝。我已經添加了另一個解決方案:-) –

3

我看到這樣做的最簡單方法其實很簡單,只需使用簡單的索引引用和重塑函數:

I = [1 2; 3 4; 5 6]; 
J(:,[1,4]) = I; 
K = reshape(J',2,6)'; 

如果檢查J,它看起來像這樣:

J = 
    1  0  0  2 
    3  0  0  4 
    5  0  0  6 

矩陣K正是想:

K = 
    1  0 
    0  2 
    3  0 
    0  4 
    5  0 
    0  6 

由於埃坦噸的評論所指出的,上面是具體以此爲例,並未涵蓋一般解決方案。下面是一般解決方案,其中m和n如問題中所述。

J(:,1:(m+1):m^2) = I; 
K=reshape(J',m,m*n)'; 

如果你想進行測試,看看它的工作,只需要使用

I=reshape(1:(m*n),m,n)'; 

注:如果j已經存在,這可能會導致問題。在這種情況下,你也需要使用

J=zeros(n,m^2); 
+0

-1:這會觸發一個錯誤:「腳本賦值維度不匹配。」。即使它能奏效,這甚至不是正確的輸出。 –

+0

尺寸不匹配是由於一個錯字 - 我說J(:,1:4),但它應該說是J(:,[1,4])。我錯誤地轉錄了它,都是。錯誤已得到糾正,並且應該按預期工作。至於輸出,如果你注意,我正在描述矩陣J,這不是最終的輸出。 K是輸出,它看起來完全像Litro所要求的......至少,它是在Octave上。 –

+0

現在有效,所以我刪除了downvote。但請注意,它不是通用的,因爲它只在'I'有兩列時才起作用。 –

0

它可能不是計算最有效的解決方案,但這裏的使用kron 1班輪:

A = [1 2; 3 4; 5 6]; 
B = diag(reshape(A', 6, 1) * kron(ones(3, 1), eye(2)) 
% B = 
%  1  0 
%  0  2 
%  3  0 
%  0  4 
%  5  0 
%  0  6 

如果A是n×m的這個可推廣:

diag(reshape(A.', n*m, 1)) * kron(ones(n,1), eye(m))