2014-12-15 3 views
5

Vorrei ottenere l'indice di un valore per ogni colonna in una matrice M. Per esempio:Come ottenere un valore da ogni colonna in una matrice Numpy

M = matrix([[0, 1, 0], 
      [4, 2, 4], 
      [3, 4, 1], 
      [1, 3, 2], 
      [2, 0, 3]]) 

In pseudocodice, mi piacerebbe fare qualcosa di simile:

for col in M: 
    idx = numpy.where(M[col]==0) # Only for columns! 

e hanno idx essere 0, 4, 0 per ogni colonna.

Ho provato a utilizzare where, ma non capisco il valore restituito, che è una tupla di matrici.

risposta

3

La tupla di matrici è una raccolta di elementi adatti all'indicizzazione. L'output avrà la forma delle matrici di indicizzazione (o matrici) e ogni elemento nell'output verrà selezionato dall'array originale utilizzando il primo array come indice della prima dimensione, il secondo come indice della seconda dimensione, e così via. In altre parole, questo:

>>> numpy.where(M == 0) 
(matrix([[0, 0, 4]]), matrix([[0, 2, 1]])) 
>>> row, col = numpy.where(M == 0) 
>>> M[row, col] 
matrix([[0, 0, 0]]) 
>>> M[numpy.where(M == 0)] = 1000 
>>> M 
matrix([[1000, 1, 1000], 
     [ 4, 2, 4], 
     [ 3, 4, 1], 
     [ 1, 3, 2], 
     [ 2, 1000, 3]]) 

La sequenza potrebbe essere ciò che ti confonde. Procede in ordine appiattito - quindi M[0,2] appare in secondo luogo, non terzo. Se avete bisogno di riordinare loro, si potrebbe fare questo:

>>> row[0,col.argsort()] 
matrix([[0, 4, 0]]) 

È inoltre potrebbe essere meglio utilizzare le matrici invece di matrici. In questo modo puoi manipolare la forma degli array, che è spesso utile! Nota anche il trucco basato sulla trasposizione di ajcr, che è probabilmente preferibile all'utilizzo di argsort.

Infine, c'è anche un metodo nonzero che fa la stessa cosa di where in questo caso. Utilizzando il trucco trasposta ora:

>>> (M == 0).T.nonzero() 
(matrix([[0, 1, 2]]), matrix([[0, 4, 0]])) 
0

Il risultato di where(M == 0) sarebbe simile a questa

(matrix([[0, 0, 4]]), matrix([[0, 2, 1]])) prima matrice ti dice le righe in cui 0 s sono e seconda matrice ti dice le colonne in cui 0 s sono.

Out[4]: 
matrix([[0, 1, 0], 
     [4, 2, 4], 
     [3, 4, 1], 
     [1, 3, 2], 
     [2, 0, 3]]) 

In [5]: np.where(M == 0) 
Out[5]: (matrix([[0, 0, 4]]), matrix([[0, 2, 1]])) 

In [6]: M[0,0] 
Out[6]: 0 

In [7]: M[0,2] #0th row 2nd column 
Out[7]: 0 

In [8]: M[4,1] #4th row 1st column 
Out[8]: 0 
2

In alternativa al np.where, si potrebbe forse usare np.argwhere per restituire una matrice di indici in cui la matrice soddisfa la condizione:

>>> np.argwhere(M == 0) 
array([[[0, 0]], 

     [[0, 2]], 

     [[4, 1]]]) 

Questo voi ogni gli indici racconta nel formato [row, column] dove la condizione è stata soddisfatta.

Se preferite il formato di questo array di output per essere raggruppati per colonna piuttosto che fila, (vale a dire, [column, row]), basta usare il metodo sulla trasposizione della matrice:

>>> np.argwhere(M.T == 0).squeeze() 
array([[0, 0], 
     [1, 4], 
     [2, 0]]) 

I anche usato np.squeeze qui per sbarazzarsi dell'asse 1, così che ci rimane un array 2D. La sequenza desiderata è la seconda colonna, ovvero np.argwhere(M.T == 0).squeeze()[:, 1].

+0

Sì, hai ragione, usare la trasposizione è meglio di "argsort" qui. – senderle

0

Questo non è nulla di nuovo in ciò che è stato già suggerito, ma una soluzione one-line è:

>>> np.where(np.array(M.T)==0)[-1] 
array([0, 4, 0]) 

(io d'accordo che NumPy matrix oggetti sono più problemi di quanto valgano).

0
>>> M = np.array([[0, 1, 0], 
...    [4, 2, 4], 
...    [3, 4, 1], 
...    [1, 3, 2], 
...    [2, 0, 3]]) 
>>> [np.where(M[:,i]==0)[0][0] for i in range(M.shape[1])] 
[0, 4, 0] 
+2

Anche se questa potrebbe essere una soluzione corretta al problema, si consiglia di spiegare che cosa fa il codice in modo che il richiedente possa capire perché la soluzione funziona invece di incollarla alla cieca. – SeinopSys