2013-07-08 18 views
5

In this question viene spiegato come accedere alle parti triagulari lower e upper di una determinata matrice, ad esempio:trasforma la parte triangolare superiore/inferiore di una matrice simmetrica (array 2D) in una matrice 1D e la restituisce al formato 2D

m = np.matrix([[11, 12, 13], 
       [21, 22, 23], 
       [31, 32, 33]]) 

Qui necessità di trasformare la matrice in un array 1D, che può essere fatto facendo:

indices = np.triu_indices_from(m) 
a = np.asarray(m[indices])[-1] 
#array([11, 12, 13, 22, 23, 33]) 

Dopo aver fatto molti calcoli con a, cambiando i valori, sarà utilizzato per riempire un sy serie mmetric 2D:

new = np.zeros(m.shape) 
for i,j in enumerate(zip(*indices)): 
    new[j]=a[i] 
    new[j[1],j[0]]=a[i] 

Tornando:

array([[ 11., 12., 13.], 
     [ 12., 22., 23.], 
     [ 13., 23., 33.]]) 

Esiste un modo migliore per ottenere questo risultato? Più in particolare, evitando il loop Python per ricostruire l'array 2D?

risposta

5

Vuoi semplicemente creare un array simmetrico? Puoi saltare completamente gli indici diagonali.

>>> m=np.array(m) 
>>> inds = np.triu_indices_from(m,k=1) 
>>> m[(inds[1], inds[0])] = m[inds] 
>>> m 
array([[11, 12, 13], 
     [12, 22, 23], 
     [13, 23, 33]]) 

Creazione di un array simmetrico da un:

>>> new = np.zeros((3,3)) 
>>> vals = np.array([11, 12, 13, 22, 23, 33]) 
>>> inds = np.triu_indices_from(new) 
>>> new[inds] = vals 
>>> new[(inds[1], inds[0])] = vals 
>>> new 
array([[ 11., 12., 13.], 
     [ 12., 22., 23.], 
     [ 13., 23., 33.]]) 
+0

devo elaborare la matrice medio termine 'a' prima di tornare al simmetrica' 2D-array' –

+0

è possibile manipolare 'm [indup ] 'finché restituisce una matrice numerica 1D nell'ordine corretto. C'è un problema particolare con questo? – Daniel

+0

un deve venire da 'array ([11, 12, 13, 22, 23, 33]) 'a un array di' matrice 2D corrispondente ([[11,12,13], [12,22,23], [13,23,33]]) ' –

3

È possibile utilizzare Array Creation Routines come numpy.triu, numpy.tril e numpy.diag per creare una matrice simmetrica da un triangolare. Ecco un semplice esempio 3x3.

a = np.array([[1,2,3],[4,5,6],[7,8,9]]) 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 

a_triu = np.triu(a, k=0) 
array([[1, 2, 3], 
     [0, 5, 6], 
     [0, 0, 9]]) 

a_tril = np.tril(a, k=0) 
array([[1, 0, 0], 
     [4, 5, 0], 
     [7, 8, 9]]) 

a_diag = np.diag(np.diag(a)) 
array([[1, 0, 0], 
     [0, 5, 0], 
     [0, 0, 9]]) 

Aggiungere la trasposizione e sottrarre la diagonale:

a_sym_triu = a_triu + a_triu.T - a_diag 
array([[1, 2, 3], 
     [2, 5, 6], 
     [3, 6, 9]]) 

a_sym_tril = a_tril + a_tril.T - a_diag 
array([[1, 4, 7], 
     [4, 5, 8], 
     [7, 8, 9]]) 
+0

Grazie per la punta;) –

+0

I eseguite stessi passaggi ma 'a' risulta essere ' array ([[22., 12., 13.], [12., 44., 23.], [13., 23., 66.]]) ' Gli elementi diagonali sono aggiunti a se stessi – Madhav

+1

@Madhav, numpy può aver aggiornato np.tril e np.triu poiché questo post include le diagonali quando k = 0. Oppure la mia risposta originale potrebbe essere semplicemente sbagliata. L'ho corretto sottraendo la diagonale con np.diag. –