2015-04-25 136 views
5

Diciamo ho un matrice quadrata come ingresso:pitone - NumPy - eliminando più righe e colonne da una matrice

array([[0, 1, 1, 0], 
     [1, 1, 1, 1], 
     [1, 1, 1, 1], 
     [0, 1, 1, 0]]) 

voglio contare i nonzeros nella matrice dopo rimozione delle righe 2 e 3 e colonne 2 e 3. Successivamente voglio fare lo stesso per le righe 3 e 4 e colonne 3 e 4. Quindi l'uscita dovrebbe essere:

0 # when removing rows/cols 2 and 3 
3 # when removing rows/cols 3 and 4 

Ecco la soluzione ingenua utilizzando np.delete:

import numpy as np 
a = np.array([[0,1,1,0],[1,1,1,1],[1,1,1,1],[0,1,1,0]]) 
np.count_nonzero(np.delete(np.delete(a, (1,2), axis=0), (1,2), axis=1)) 
np.count_nonzero(np.delete(np.delete(a, (2,3), axis=0), (2,3), axis=1)) 

Ma np.delete restituisce un nuovo array. Esiste un metodo più veloce, che comporta l'eliminazione di righe e colonne contemporaneamente? Si può usare il mascheramento? La documentation su np.delete legge:

Spesso è preferibile utilizzare una maschera booleano.

Come faccio a farlo? Grazie.

+1

Quando si dà questo tipo di domande, è importante per spiegare le dimensioni di ciascuna variabile (ad esempio dimensioni della matrice. , numero di righe cancellate, ecc.) perché la qualità di molte risposte dipende da questo. – Veedrac

+0

@Veedrac Grazie! Lo so. Cercherò di non dimenticare in futuro. In questo caso il numero di righe nella matrice quadrata non è mai stato superiore a 10. –

risposta

5

Invece di eliminare le colonne e le righe che non si desidera, è più facile per selezionare quelli che non desidera. Si noti inoltre che è normale iniziare a contare le righe e le colonne da zero. Per ottenere il primo esempio, si vuole così a selezionare tutti gli elementi in righe 0 e 3 e nelle righe 0 e 3. Questo richiede advanced indexing, per i quali è possibile utilizzare la ix_ utility function:

In [25]: np.count_nonzero(a[np.ix_([0,3], [0,3])]) 
Out[25]: 0 

Per il secondo esempio, si vogliono selezionare le righe 0 e 1 e le colonne 0 e 1, che può essere fatto utilizzando basic slicing:

In [26]: np.count_nonzero(a[:2,:2]) 
Out[26]: 3 
+0

'numpy.ix' era esattamente quello che cercavo. Dovrei sedermi e leggere la documentazione numpy un giorno. Grazie! –

+2

Leggere interi manuali solo per scoprire funzioni oscure ma utili non è molto divertente. È possibile lavorare meglio attraverso alcune esercitazioni di base e alcune più dettagliate sull'importazione, ma concetti confusi come la trasmissione e quello sull'indicizzazione che ho collegato nella mia risposta. –

+0

Il primo riguarda ancora la copia.Si noti che se si eliminano solo due righe e colonne con una matrice grande, si possono prendere le somme delle 9 sottomatrici tra le righe cancellate. Quelle fette non comporterebbero copie. – Veedrac

3

Non è necessario modificare l'array originale eliminando righe/colonne, per contare il numero di elementi diversi da zero. È sufficiente utilizzare l'indicizzazione,

a = np.array([[0,1,1,0],[1,1,1,1],[1,1,1,1],[0,1,1,0]]) 
irows, icols = np.indices(a.shape) 
mask = (irows!=2)&(irows!=3)&(icols!=2)&(icols!=3) 
np.count_nonzero(a[mask]) 
+0

Questa è anche una buona soluzione, ma non è possibile scrivere una maschera esplicita per ogni caso. Grazie per la risposta. –

+1

@ tommy.carstensen Ben si potrebbe facilmente estendere questo, definendo la funzione che accetta i numeri di righe/colonne e genera una maschera corrispondente. Anche se sono d'accordo sul fatto che se si può vivere con la selezione delle colonne rimanenti con 'np.ix_', sarebbe un approccio migliore. – rth

Problemi correlati