suppression de lignes dans le tableau numpy

88

J'ai un tableau qui pourrait ressembler à ceci:

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

Notez que l'une des lignes a une valeur zéro à la fin. Je souhaite supprimer toute ligne contenant un zéro, tout en conservant toute ligne contenant des valeurs non nulles dans toutes les cellules.

Mais le tableau aura un nombre de lignes différent à chaque fois qu'il est rempli, et les zéros seront situés dans des lignes différentes à chaque fois.

J'obtiens le nombre d'éléments non nuls dans chaque ligne avec la ligne de code suivante:

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

Pour le tableau ci-dessus, NumNonzeroElementsInRowscontient: [5 4]

Le cinq indique que toutes les valeurs possibles de la ligne 0 sont différentes de zéro, tandis que le quatre indique que l'une des valeurs possibles de la ligne 1 est un zéro.

Par conséquent, j'essaie d'utiliser les lignes de code suivantes pour trouver et supprimer des lignes qui contiennent des valeurs nulles.

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

Mais pour une raison quelconque, ce code ne semble rien faire, même si faire beaucoup de commandes d'impression indique que toutes les variables semblent se remplir correctement menant au code.

Il doit y avoir un moyen simple de simplement «supprimer toute ligne contenant une valeur nulle».

Quelqu'un peut-il me montrer quel code écrire pour accomplir cela?

MédicalMath
la source

Réponses:

163

La méthode la plus simple pour supprimer des lignes et des colonnes de tableaux est la numpy.deleteméthode.

Supposons que j'ai le tableau suivant x:

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

Pour supprimer la première ligne, procédez comme suit:

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

Pour supprimer la troisième colonne, procédez comme suit:

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

Ainsi, vous pouvez trouver les index des lignes qui ont un 0, les mettre dans une liste ou un tuple et passer ceci comme deuxième argument de la fonction.

Jaidev Deshpande
la source
Merci! J'ai eu le même problème et je ne pouvais pas comprendre pourquoi le simple appel numpy.delete(x, index)ne fonctionnait pas.
Antimoine
6
notez que la documentation numpy delete () indique que "Souvent, il est préférable d'utiliser un masque booléen" car un nouveau tableau est renvoyé - un exemple est fourni sous ce lien
arturomp
1
@arturomp mais le masque est non destructif. Un appel à delete () prend-il du temps / de la mémoire?
Nathan
13

Voici une ligne unique (oui, elle est similaire à celle de user333700, mais un peu plus simple):

>>> 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]])

À propos, cette méthode est beaucoup, beaucoup plus rapide que la méthode de tableau masqué pour les grandes matrices. Pour une matrice de 2048 x 5, cette méthode est environ 1000 fois plus rapide.

À propos, la méthode de user333700 (d'après son commentaire) a été légèrement plus rapide dans mes tests, même si cela me déroute.

Justin Peel
la source
3
"any" peut court-circuiter, dès que le premier vrai cas est détecté, il peut s'arrêter, tandis que "all" doit vérifier toutes les conditions. Donc, pas ("~" dans numpy) aucun, devrait en général être plus rapide que tout.
Josef
4
@ user333700, les deux peuvent court-circuiter, juste à des choses différentes. anycourt-circuit à vrai au premier cas vrai détecté; allcourt-circuit à faux au premier faux cas détecté. Dans ce cas, le court-circuit devrait être un match nul, mais ne pas faire le plus devrait le ralentir à mon avis.
Justin Peel
5

Ceci est similaire à votre approche d'origine et utilisera moins d'espace que la réponse d' unutbu , mais je soupçonne que ce sera plus lent.

>>> 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]])

Au fait, votre ligne p.delete()ne fonctionne pas pour moi - ndarrays n'ont pas d' .deleteattribut.

mtrw
la source
8
un peu plus simple: p [~ (p == 0) .any (1)] ou plus explicite pour les lignes: p [~ (p == 0) .any (1),:]
Josef
2

numpy fournit une fonction simple pour faire exactement la même chose: en supposant que vous ayez un tableau masqué 'a', appeler numpy.ma.compress_rows (a) supprimera les lignes contenant une valeur masquée. Je suppose que c'est beaucoup plus rapide de cette façon ...

jeps
la source
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.)])
Prokhozhii
la source
-1

Je serais peut-être trop tard pour répondre à cette question, mais je voulais partager ma contribution au profit de la communauté. Pour cet exemple, permettez-moi d'appeler votre matrice «ANOVA», et je suppose que vous essayez simplement de supprimer des lignes de cette matrice avec des 0 uniquement dans la 5ème colonne.

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]
troymyname00
la source