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!
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
.
É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
.