web-dev-qa-db-fra.com

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/matrice numpy sont les mêmes. J'ai essayé d'utiliser reduce du funcequal, mais cela 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 deuxième cas est-elle également évaluée à True, alors qu'elle devrait être False?

Merci pour toute aide!

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

Comparez 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 partage une valeur commune si toutes les valeurs de cette colonne sont vraies:

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

Le problème avec np.equal.reduce peut être vu en microanalysant ce qui se passe lorsqu'il est appliqué à [1, 0, 0, 1]:

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

Les deux premiers éléments, 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, ce qui n'est pas le résultat souhaité.

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

44
unutbu

Étant donné l'explication impressionnante d'ubuntu, vous pouvez utiliser reduce pour résoudre votre problème, mais vous devez l'appliquer à bitwise_and Et bitwise_or Plutôt qu'à equal. Par conséquent, cela ne fonctionnera pas avec les tableaux à virgule flottante:

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)

Fondamentalement, vous comparez les bits de chaque élément de 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 N'interceptera pas le cas où des bits sont introduits plutôt que supprimés:

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 deuxième coumn est clairement faux. Nous devons utiliser bitwise_or Pour piéger de 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 elle a l'avantage de ne pas créer d'énormes tableaux temporaires si votre entrée est énorme. Les tableaux temporaires ne doivent être aussi grands que la première ligne de votre matrice.

[~ # ~] modifier [~ # ~]

Sur la base de cela 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. En l'occurrence, les opérations bitwise_and.reduce() affichées ne peuvent renvoyer que zéro ou un car bitwise_and.identity Est 1, Pas -1. Je garde cette réponse dans l'espoir que numpy sera corrigé et que la réponse deviendra valide.

Modifier

Il semble qu'il y aura bientôt un changement de numpy. Certainement à bitwise_and.identity, Et peut-être aussi un paramètre optionnel à réduire.

Modifier

Bonnes nouvelles tout le monde. L'identité de np.bitwise_and A été définie sur -1 À partir de la version 1.12.0.

8
Mad Physicist