2010-10-18 12 views
40

Angenommen, ich habe eine NxN Matrix A, V ein Indexvektor eine Untergruppe bestehend aus den Zahlen 1: N und einen Wert K, und ich möchte, dies zu tun:Wie lege ich Werte auf der Diagonale fest?

for i = V 
    A(i,i) = K 
end 

ein Weg gibt es zu tun Dies in einer Aussage w/Vektorisierung?

z.B. A (etwas) = K

Die Aussage A(V,V) = K wird nicht funktionieren, es weist Elemente außerhalb der Diagonalen, und das ist nicht das, was ich will. zB:

>> A = zeros(5); 
>> V = [1 3 4]; 
>> A(V,V) = 1 

A = 

1  0  1  1  0 
0  0  0  0  0 
1  0  1  1  0 
1  0  1  1  0 
0  0  0  0  0 

Antwort

60

ich EYE in der Regel für diese Verwendung:

A = magic(4) 
A(logical(eye(size(A)))) = 99 

A = 
    99  2  3 13 
    5 99 10  8 
    9  7 99 12 
    4 14 15 99 

Alternativ können Sie nur die Liste der linearen Indizes erstellen, da von einem diagonalen Element zum nächsten, dauert es nRows+1 Schritte:

[nRows,nCols] = size(A); 
A(1:(nRows+1):nRows*nCols) = 101 
A = 
    101  2  3 13 
    5 101 10  8 
    9  7 101 12 
    4 14 15 101 

Wenn Sie nur eine Teilmenge der Diagonalelemente zugreifen möchten, müssen Sie eine Liste von diagonalen Indizes erstellen:

subsetIdx = [1 3]; 
diagonalIdx = (subsetIdx-1) * (nRows + 1) + 1; 
A(diagonalIdx) = 203 
A = 
    203  2  3 13 
    5 101 10  8 
    9  7 203 12 
    4 14 15 101 

Alternativ können Sie einen logischen Index Array erstellen mit diag (funktioniert nur für quadratische Arrays)

diagonalIdx = false(nRows,1); 
diagonalIdx(subsetIdx) = true; 
A(diag(diagonalIdx)) = -1 
A = 
    -1  2  3 13 
    5 101 10  8 
    9  7 -1 12 
    4 14 15 101 
+0

cool, es funktioniert! wird akzeptieren, wenn der blöde Timer abgelaufen ist –

+0

@Jason S: Danke! Ich finde das eigentlich ein nerviges Problem; Ich versuche, oft zuerst 'diag' zu verwenden, bevor ich erinnere mich, verwenden' Auge' – Jonas

+0

für die zweiten letzten Beispiele, schlage ich vor, Matlab sub2ind Funktion zu finden, die absolute Indizes zu verwenden. Meiner Meinung nach ist dies der einfachste (und lesbarste) Ansatz und könnte Ihre letzten beiden Vorschläge ersetzen. – tc88

21
>> tt = zeros(5,5) 
tt = 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
>> tt(1:6:end) = 3 
tt = 
    3  0  0  0  0 
    0  3  0  0  0 
    0  0  3  0  0 
    0  0  0  3  0 
    0  0  0  0  3 

und allgemeiner: auf die ist

>> V=[1 2 5]; N=5; 
>> tt = zeros(N,N); 
>> tt((N+1)*(V-1)+1) = 3 
tt = 
    3  0  0  0  0 
    0  3  0  0  0 
    0  0  0  0  0 
    0  0  0  0  0 
    0  0  0  0  3 

Diese basiert Tatsache, dass auf Matrizen als eindimensionale Arrays (Vektoren) zugegriffen werden kann, wobei die 2 Indizes (m, n) durch eine lineare Abbildung m * N + n ersetzt werden.

+0

Ich habe Ihre Lösung erst gesehen, nachdem ich meine Bearbeitung eingereicht hatte. +1 für schneller, obwohl meine Lösung ein bisschen allgemeiner ist :) – Jonas

+1

Ich mag die tt (1: n + 1: end) Methode, wirklich sauber! – Erika

2
A = zeros(7,6); 
V = [1 3 5]; 

[n m] = size(A); 
diagIdx = 1:n+1:n*m; 
A(diagIdx(V)) = 1 

A = 
    1  0  0  0  0  0 
    0  0  0  0  0  0 
    0  0  1  0  0  0 
    0  0  0  0  0  0 
    0  0  0  0  1  0 
    0  0  0  0  0  0 
    0  0  0  0  0  0 
2

Angenommen, K ist der Wert. Der Befehl

A=A-diag(K-diag(A)) 

kann etwas schneller sein

>> A=randn(10000,10000); 

>> tic;A(logical(eye(size(A))))=12;toc 

verstrichene Zeit 0,517575 Sekunden ist.

>> tic;A=A+diag((99-diag(A)));toc 

Die verstrichene Zeit ist 0.353408 Sekunden.

Aber es verbraucht mehr Speicher.

+0

Ich benutzte 'A (logisch (Auge (Größe (A)))) = K' flexibel schnell und zuverlässig – Vass

1

würde ich sub2ind verwenden und die diagonalen Indizes x und y-Parameter übergeben:

A = zeros(4) 
V=[2 4] 

idx = sub2ind(size(A), V,V) 
% idx = [6, 16] 

A(idx) = 1 

% A = 
% 0  0  0  0 
% 0  1  0  0 
% 0  0  0  0 
% 0  0  0  1 
Verwandte Themen