Stacking diagonal matrices generated from rows of other matrix

8 ビュー (過去 30 日間)
Distelfink
Distelfink 2022 年 3 月 4 日
コメント済み: Distelfink 2022 年 3 月 4 日
Dear matlab forum,
I am pretty new to matlab and would like to do the following. Consider the matrix C.
C=magic(4)
C = 4×4
16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1
From the second to fourth entries of the rows of C, I want to create diagonal matrices, which I want to stack to generate my target matrix D. I could do this with the following loop:
D=[];
for i=1:4
A=diag(C(i,2:4));
D=[D;A];
end
D
D = 12×3
2 0 0 0 3 0 0 0 13 11 0 0 0 10 0 0 0 8 7 0 0 0 6 0 0 0 12 14 0 0
How can I do this operation efficiently, i.e. in vectorized form and without using a loop?
Thanks a lot in advance!

採用された回答

Stephen23
Stephen23 2022 年 3 月 4 日
編集済み: Stephen23 2022 年 3 月 4 日
The simplest approach is probably just to use an intermediate cell array:
N = 4;
M = magic(N);
C = cell(1,N);
for k = 1:N
C{k} = diag(M(k,2:4));
end
A = vertcat(C{:})
A = 12×3
2 0 0 0 3 0 0 0 13 11 0 0 0 10 0 0 0 8 7 0 0 0 6 0 0 0 12 14 0 0
  2 件のコメント
Distelfink
Distelfink 2022 年 3 月 4 日
Thanks, Stephen! I guess you meant C=cell(1,N) - but it works anyway. Still, is there a way to circumvent the for loop? I am asking because I will have to do this on a large scale (the magic matrix is just an example of course) and am looking for an efficient way
Stephen23
Stephen23 2022 年 3 月 4 日
編集済み: Stephen23 2022 年 3 月 4 日
"Still, is there a way to circumvent the for loop?"
Possibly, with some effort and fiddling around with indices or something like that.
"...looking for an efficient way "
Loops are efficient. Why does this incorrect rumour persist that loops are not efficient?
There is absolutely no reason to believe that vectorized code of this task will be faster or use less memory: in many instances vectorized code is slower because it requires larger intermediate arrays. Not only that, but a fully vectorized solution would considerably obfuscate the intent of your code, making maintaining the code much slower (total time cost includes run time, write time, debugging time, maintenance time).
Most likely you have already spent more time on this thread than you could save making the code faster.
I would use the loop with a cell array and VERTCAT: it is efficient and its intent is clear.

サインインしてコメントする。

その他の回答 (4 件)

Matt J
Matt J 2022 年 3 月 4 日
C=magic(4)
C = 4×4
16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1
c=C(:,2:4);
[m,n]=size(c);
D=repmat(eye(n),m,1);
D(logical(D))=c(:)
D = 12×3
2 0 0 0 3 0 0 0 13 11 0 0 0 10 0 0 0 8 7 0 0 0 6 0 0 0 12 14 0 0
  1 件のコメント
Distelfink
Distelfink 2022 年 3 月 4 日
Thank you, Matt! Also for the other answer!

サインインしてコメントする。


Matt J
Matt J 2022 年 3 月 4 日
C=magic(4)
C = 4×4
16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1
c=C(:,2:4);
[m,n]=size(c); p=m*n;
D=zeros(p,n);
D( (1:n:p)'+ (0:n-1)*(p+1) )=c(:)
D = 12×3
2 0 0 0 3 0 0 0 13 11 0 0 0 10 0 0 0 8 7 0 0 0 6 0 0 0 12 14 0 0

KSSV
KSSV 2022 年 3 月 4 日
This would be better than given code:
C=magic(4) ;
D=zeros(3,3,4);
for i=1:4
D(:,:,i)=diag(C(i,2:4));
end
D = reshape(permute(D,[2,1,3]),size(D,2),[])'
D = 12×3
2 0 0 0 3 0 0 0 13 11 0 0 0 10 0 0 0 8 7 0 0 0 6 0 0 0 12 14 0 0
  1 件のコメント
Distelfink
Distelfink 2022 年 3 月 4 日
Thank you! This still uses a for loop, however. Is there a vectorized form as well?

サインインしてコメントする。


Arif Hoq
Arif Hoq 2022 年 3 月 4 日
2nd to 4th diagonal of C
C=magic(4)
C = 4×4
16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1
C1=tril(C,-1);
C2=triu(C1,-1)
C2 = 4×4
0 0 0 0 5 0 0 0 0 7 0 0 0 0 15 0
  1 件のコメント
Distelfink
Distelfink 2022 年 3 月 4 日
Thank you! I am not quite sure whether I understand your answer. How does this yield the matrix D?

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by