2010-10-06 80 views
49

Ho un array che potrebbe essere il seguente:eliminazione righe nella matrice NumPy

ANOVAInputMatrixValuesArray = [[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 
0.53172222], [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]] 

noti che una delle righe ha un valore zero al termine. Voglio eliminare qualsiasi riga che contiene uno zero, mantenendo qualsiasi riga che contenga valori diversi da zero in tutte le celle.

Ma la matrice avrà un numero diverso di righe ogni volta che viene popolata e gli zeri saranno posizionati in righe diverse ogni volta.

ottengo il numero di elementi diversi da zero in ciascuna riga con la seguente riga di codice:

NumNonzeroElementsInRows = (ANOVAInputMatrixValuesArray != 0).sum(1) 

Per la matrice sopra, NumNonzeroElementsInRows contiene: [5 4]

I cinque indica che tutti i valori possibili nella riga 0 sono diversi da zero, mentre i quattro indicano che uno dei possibili valori nella riga 1 è uno zero.

Pertanto, sto cercando di utilizzare le seguenti righe di codice per trovare ed eliminare righe contenenti valori zero.

for q in range(len(NumNonzeroElementsInRows)): 
    if NumNonzeroElementsInRows[q] < NumNonzeroElementsInRows.max(): 
     p.delete(ANOVAInputMatrixValuesArray, q, axis=0) 

Ma per qualche ragione, questo codice non sembra di fare nulla, anche se facendo un sacco di comandi di stampa indica che tutte le variabili sembrano essere popolando correttamente che porta al codice.

Ci deve essere un modo semplice per "cancellare qualsiasi riga che contenga un valore zero".

Qualcuno può mostrarmi quale codice scrivere per realizzare questo?

risposta

4

Questo è simile all'approccio originale e utilizzerà meno spazio di unutbu's answer, ma sospetto che sarà più lento.

>>> import numpy as np 
>>> p = np.array([[1.5, 0], [1.4,1.5], [1.6, 0], [1.7, 1.8]]) 
>>> p 
array([[ 1.5, 0. ], 
     [ 1.4, 1.5], 
     [ 1.6, 0. ], 
     [ 1.7, 1.8]]) 
>>> nz = (p == 0).sum(1) 
>>> q = p[nz == 0, :] 
>>> q 
array([[ 1.4, 1.5], 
     [ 1.7, 1.8]]) 

Tra l'altro, la vostra linea p.delete() non funziona per me - ndarray s non hanno un attributo .delete.

+8

un po 'più semplice: p [~ (p == 0) .any (1)] o più esplicito per le righe: p [~ (p == 0) .any (1),:] – user333700

+0

@ user333700 - Questa dovrebbe essere una risposta - avrai sicuramente il mio voto! 'any' è molto più chiaro di' sum' in questo uso. – mtrw

12

Ecco un uno di linea (sì, è simile a user333700 di, ma un po 'più semplice):

>>> import numpy as np 
>>> arr = np.array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 0.53172222], 
       [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]]) 
>>> print arr[arr.all(1)] 
array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875 , 0.53172222]]) 

proposito, questo metodo è molto più velocemente rispetto al metodo matrice mascherato per grandi matrici . Per una matrice 2048 x 5, questo metodo è circa 1000 volte più veloce.

A proposito, il metodo di user333700 (dal suo commento) è stato leggermente più veloce nei miei test, anche se mi sorprende il perché.

+3

"any" può cortocircuitare, non appena viene rilevato il primo caso vero, può fermarsi, mentre "all" deve controllare tutte le condizioni. Quindi, non ("~" in numpy), dovrebbe in generale essere più veloce di tutti. – user333700

+3

@ user333700, entrambi possono causare cortocircuiti, solo per cose diverse. 'qualsiasi' cortocircuito su true al primo vero caso rilevato; 'tutti' cortocircuiti su false al primo caso falso rilevato. In questo caso, il cortocircuito dovrebbe essere un pareggio, ma fare l'extra non dovrebbe renderlo più lento a mio parere. –

2

numpy fornisce una semplice funzione per fare esattamente la stessa cosa: supponendo di avere un array mascherato 'a', chiamando numpy.ma.compress_rows (a) eliminerà le righe contenenti un valore mascherato. Immagino che questo sia molto più veloce in questo modo ...

96

Il metodo più semplice per eliminare righe e colonne dagli array è il metodo numpy.delete.

Supponiamo Ho la seguente matrice x:

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

Per eliminare la prima riga, procedere come segue:

x = numpy.delete(x, (0), axis=0) 

Per eliminare la terza colonna, fare questo:

x = numpy.delete(x,(2), axis=1) 

Quindi potresti trovare gli indici delle righe che hanno uno 0 in loro, metterli in una lista o in una tupla e passare questo come il secondo argomento della funzione.

+0

Grazie! Ho avuto lo stesso problema, e non riuscivo a capire perché il semplice richiamo di 'numpy.delete (x, index)' non funzionasse. – Antimony

+3

nota che il [numpy delete() docs] (https://docs.scipy.org/doc/numpy/reference/generated/numpy.delete.html) indica che "Spesso è preferibile usare una maschera booleana" dal viene restituito un nuovo array - un esempio è fornito sotto quel collegamento – arturomp

0

Potrei essere in ritardo per rispondere a questa domanda, ma ho voluto condividere il mio contributo a beneficio della comunità. Per questo esempio, permettimi di chiamare la tua matrice 'ANOVA' e suppongo che tu stia solo cercando di rimuovere le righe da questa matrice con 0 solo nella quinta colonna.

indx = [] 
for i in range(len(ANOVA)): 
    if int(ANOVA[i,4]) == int(0): 
     indx.append(i) 

ANOVA = [x for x in ANOVA if not x in indx]