l'eliminazione di righe nell'array numpy


90

Ho un array che potrebbe assomigliare a questo:

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

Notare che una delle righe ha un valore zero alla fine. Voglio eliminare qualsiasi riga che contiene uno zero, mantenendo qualsiasi riga che contiene valori diversi da zero in tutte le celle.

Ma l'array avrà un numero diverso di righe ogni volta che viene popolato e gli zeri saranno posizionati in righe diverse ogni volta.

Ottengo il numero di elementi diversi da zero in ogni riga con la seguente riga di codice:

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

Per la matrice sopra, NumNonzeroElementsInRowscontiene: [5 4]

Il cinque indica che tutti i possibili valori nella riga 0 sono diversi da zero, mentre il quattro indica 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 che contengono valori zero.

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

Ma per qualche motivo, questo codice sembra non fare nulla, anche se l'esecuzione di molti comandi di stampa indica che tutte le variabili sembrano essere popolate correttamente fino al codice.

Ci deve essere un modo semplice per "eliminare qualsiasi riga che contiene un valore zero".

Qualcuno può mostrarmi quale codice scrivere per ottenere questo risultato?

Risposte:


166

Il modo più semplice per eliminare righe e colonne dagli array è il numpy.deletemetodo.

Supponiamo di avere il seguente array x:

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

Per eliminare la prima riga, procedi come segue:

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

Per eliminare la terza colonna, procedi come segue:

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

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


Grazie! Ho avuto lo stesso problema e non sono riuscito a capire perché la semplice chiamata numpy.delete(x, index)non funzionasse.
Antimonio

6
nota che i documenti di numpy delete () indicano che "Spesso è preferibile usare una maschera booleana" poiché viene restituito un nuovo array - un esempio è fornito sotto quel link
arturomp

1
@arturomp ma la maschera non è distruttiva. Una chiamata a delete () richiede tempo / memoria?
Nathan

14

Ecco un one liner (sì, è simile a quello di user333700, 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]])

A proposito, questo metodo è molto, molto più veloce del metodo con matrice mascherata per matrici di grandi dimensioni. 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 lascia perplesso il motivo.


3
"qualsiasi" può andare in cortocircuito, non appena viene rilevato il primo caso vero, può fermarsi, mentre "tutti" devono controllare tutte le condizioni. Quindi, non ("~" in numpy) nessuno, dovrebbe in generale essere più veloce di tutti.
Josef

4
@ user333700, entrambi possono cortocircuitare, solo per cose diverse. anycortocircuiti a vero al primo caso vero rilevato; allcortocircuiti verso falso al primo falso caso rilevato. In questo caso, il cortocircuito dovrebbe essere un pareggio, ma fare l'extra no dovrebbe renderlo più lento secondo me.
Justin Peel

5

Questo è simile al tuo approccio originale e utilizzerà meno spazio rispetto alla risposta di unutbu , 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]])

A proposito, la tua linea p.delete()non funziona per me - ndarraynon hanno un .deleteattributo.


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

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) verranno eliminate le righe contenenti un valore mascherato. Immagino che in questo modo sia molto più veloce ...


1
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[np.where(arr != 0.)])

-1

Potrei essere troppo tardi per rispondere a questa domanda, ma volevo condividere il mio contributo a beneficio della comunità. Per questo esempio, fammi chiamare la tua matrice "ANOVA" e presumo 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]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.