2013-04-24 1 views
26

Come dividere una fila di array numpy per la somma di tutti i valori in questa riga?dividere numpy riga per riga somma

Questo è un esempio. Ma sono abbastanza sicuro che ci sia un modo elegante e molto più efficiente di fare questo:

import numpy as np 
e = np.array([[0., 1.],[2., 4.],[1., 5.]]) 
for row in xrange(e.shape[0]): 
    e[row] /= np.sum(e[row]) 

Risultato:

array([[ 0.  , 1.  ], 
     [ 0.33333333, 0.66666667], 
     [ 0.16666667, 0.83333333]]) 

risposta

53

Metodo # 1: Utilizzare None (o np.newaxis) per aggiungere una dimensione extra in modo che la trasmissione si comporterà:

>>> e 
array([[ 0., 1.], 
     [ 2., 4.], 
     [ 1., 5.]]) 
>>> e/e.sum(axis=1)[:,None] 
array([[ 0.  , 1.  ], 
     [ 0.33333333, 0.66666667], 
     [ 0.16666667, 0.83333333]]) 

Metodo # 2: go-trasporre felice:

>>> (e.T/e.sum(axis=1)).T 
array([[ 0.  , 1.  ], 
     [ 0.33333333, 0.66666667], 
     [ 0.16666667, 0.83333333]]) 

(È possibile eliminare la parte axis= per brevità, se si vuole.)

Metodo # 3: (promosso dal commento di Jaime)

utilizzare l'argomento keepdims su sum per preservare la dimensione:

>>> e/e.sum(axis=1, keepdims=True) 
array([[ 0.  , 1.  ], 
     [ 0.33333333, 0.66666667], 
     [ 0.16666667, 0.83333333]]) 
+0

Non vedo come si può cadere il 'asse = 1'. Senza l'argomento 'axis',' sum() 'restituisce la somma di tutti i valori nella matrice. –

+18

In numpy 1.7 c'è un argomento 'keepdims' che ti permette di fare' e/e.sum (axis = 1, keepdims = True) ' – Jaime

+2

@WarrenWeckesser: Non ho detto che potresti rilasciare la parte' 1', I ha detto che è possibile rilasciare la parte 'axis ='. – DSM

5

È possibile farlo matematicamente come enter image description here.

Qui, E è la matrice originale e D è una matrice diagonale in cui ogni voce è la somma della riga corrispondente in E. Se sei abbastanza fortunato da avere un invertibile D, questo è un modo abbastanza matematicamente conveniente per fare le cose.

In NumPy:

import numpy as np 

diagonal_entries = [sum(e[row]) for row in range(e.shape[0])] 
D = np.diag(diagonal_entries) 
D_inv = np.linalg.inv(D) 
e = np.dot(e, D_inv)