Comment vérifier si toutes les valeurs dans les colonnes d'une matrice numpy sont les mêmes?

je veux vérifier si toutes les valeurs dans les colonnes d'un tableau numpy/matrice sont les mêmes. J'ai essayé d'utiliser reduceufuncequal, mais il ne semble pas fonctionner dans tous les cas:

In [55]: a = np.array([[1,1,0],[1,-1,0],[1,0,0],[1,1,0]])

In [56]: a
Out[56]: 
array([[ 1,  1,  0],
       [ 1, -1,  0],
       [ 1,  0,  0],
       [ 1,  1,  0]])

In [57]: np.equal.reduce(a)
Out[57]: array([ True, False,  True], dtype=bool)

In [58]: a = np.array([[1,1,0],[1,0,0],[1,0,0],[1,1,0]])

In [59]: a
Out[59]: 
array([[1, 1, 0],
       [1, 0, 0],
       [1, 0, 0],
       [1, 1, 0]])

In [60]: np.equal.reduce(a)
Out[60]: array([ True,  True,  True], dtype=bool)

Pourquoi la colonne du milieu, dans le second cas également évaluer True, alors qu'il devrait être <!--4?

merci de votre aide!

18
demandé sur tobigue 2013-02-13 21:33:03

2 réponses

In [45]: a
Out[45]: 
array([[1, 1, 0],
       [1, 0, 0],
       [1, 0, 0],
       [1, 1, 0]])

Comparer chaque valeur à la valeur correspondante dans la première ligne:

In [46]: a == a[0,:]
Out[46]: 
array([[ True,  True,  True],
       [ True, False,  True],
       [ True, False,  True],
       [ True,  True,  True]], dtype=bool)

Une colonne actions d'une valeur commune si toutes les valeurs de cette colonne sont remplies:

In [47]: np.all(a == a[0,:], axis = 0)
Out[47]: array([ True, False,  True], dtype=bool)

Le problème np.equal.reduce peut être vu en micro-analysant ce qui se passe quand il est appliqué à [1, 0, 0, 1]:

In [49]: np.equal.reduce([1, 0, 0, 1])
Out[50]: True

Les deux premiers points, 1 et 0 sont testés pour l'égalité et le résultat est False:

In [51]: np.equal.reduce([False, 0, 1])
Out[51]: True

Maintenant False et 0 sont testés pour l'égalité et le résultat est True:

In [52]: np.equal.reduce([True, 1])
Out[52]: True

Mais True et 1 sont égaux, donc le résultat total est True, qui n'est pas le résultat souhaité.

Le problème est que reduce tente d'accumuler le résultat "localement", alors que nous voulons un test "global" comme np.all.

31
répondu unutbu 2013-02-13 19:03:59

étant donné l'explication géniale d'ubuntu, vous pouvez utiliser reduce pour résoudre ton problème, mais vous devez l'appliquer à bitwise_and et bitwise_or plutôt que equal. En conséquence, cela ne fonctionnera pas avec virgule flottante tableaux:

In [60]: np.bitwise_and.reduce(a) == a[0]
Out[60]: array([ True, False,  True], dtype=bool)

In [61]: np.bitwise_and.reduce(b) == b[0]
Out[61]: array([ True, False,  True], dtype=bool)

en gros, vous comparez les bits de chaque élément dans la colonne. Les bits identiques sont inchangés. Différents bits sont mis à zéro. De cette façon, tout nombre qui a un zéro au lieu d'un bit changera la valeur réduite. bitwise_and ne sera pas de piège le cas où les bits sont introduits plutôt que supprimé:

In [62]: c = np.array([[1,0,0],[1,0,0],[1,0,0],[1,1,0]])

In [63]: c
Out[63]: 
array([[1, 0, 0],
       [1, 0, 0],
       [1, 0, 0],
       [1, 1, 0]])

In [64]: np.bitwise_and.reduce(c) == c[0]
Out[64]: array([ True,  True,  True], dtype=bool)

le second coumn est clairement erroné. Nous avons besoin d'utiliser bitwise_or pour piéger les nouveaux bits:

In [66]: np.bitwise_or.reduce(c) == c[0]
Out[66]: array([ True, False,  True], dtype=bool)

Réponse Finale

In [69]: np.logical_and(np.bitwise_or.reduce(a) == a[0], np.bitwise_and.reduce(a) == a[0])
Out[69]: array([ True, False,  True], dtype=bool)

In [70]: np.logical_and(np.bitwise_or.reduce(b) == b[0], np.bitwise_and.reduce(b) == b[0])
Out[70]: array([ True, False,  True], dtype=boo

In [71]: np.logical_and(np.bitwise_or.reduce(c) == c[0], np.bitwise_and.reduce(c) == c[0])
Out[71]: array([ True, False,  True], dtype=bool)

cette méthode est plus restrictive et moins élégante que la suggestion d'ubunut d'utiliser all, mais il a l'avantage de ne pas créer d'énormes temporaire des tableaux si votre entrée est énorme. Les tableaux temporaires ne devraient être aussi grands que la première rangée de votre matrice.

EDIT

sur la Base de ce Q / A et le bug que j'ai déposé avec numpy la solution fournie ne fonctionne que parce que votre tableau contient des zéros et des uns. Comme il arrive, le bitwise_and.reduce() les opérations montrées ne peuvent retourner que zéro ou un parce que bitwise_and.identity1, pas -1. Je suis en gardant cette réponse, dans l'espoir qu' numpy est corrigé et la réponse devient valide.

Modifier

on dirait qu'il va y avoir en fait un changement à numpy bientôt. Certainement bitwise_and.identity, et peut-être aussi un paramètre optionnel à réduire.

Modifier

bonnes nouvelles à tous. L'identité de np.bitwise_and a été mis à -1 version 1.12.0.

7
répondu Mad Physicist 2017-05-23 11:33:17