La logical_or
fonction de Numpy ne prend pas plus de deux tableaux à comparer. Comment puis-je trouver l'union de plus de deux tableaux? (La même question pourrait être posée en ce qui concerne Numpy logical_and
et l'obtention de l'intersection de plus de deux tableaux.)
88
any()
?Réponses:
Si vous posez des questions
numpy.logical_or
, alors non, comme le disent explicitement la documentation, les seuls paramètres sontx1, x2
, et éventuellementout
:Vous pouvez bien sûr enchaîner plusieurs
logical_or
appels comme ceci:>>> x = np.array([True, True, False, False]) >>> y = np.array([True, False, True, False]) >>> z = np.array([False, False, False, False]) >>> np.logical_or(np.logical_or(x, y), z) array([ True, True, True, False], dtype=bool)
La façon de généraliser ce type de chaînage dans NumPy est avec
reduce
:>>> np.logical_or.reduce((x, y, z)) array([ True, True, True, False], dtype=bool)
Et bien sûr, cela fonctionnera également si vous avez un tableau multidimensionnel au lieu de tableaux séparés - en fait, c'est ainsi qu'il est censé être utilisé:
>>> xyz = np.array((x, y, z)) >>> xyz array([[ True, True, False, False], [ True, False, True, False], [False, False, False, False]], dtype=bool) >>> np.logical_or.reduce(xyz) array([ True, True, True, False], dtype=bool)
Mais un tuple de trois tableaux 1D de même longueur est un array_like en termes NumPy, et peut être utilisé comme un tableau 2D.
En dehors de NumPy, vous pouvez également utiliser Python
reduce
:>>> functools.reduce(np.logical_or, (x, y, z)) array([ True, True, True, False], dtype=bool)
Cependant, contrairement à NumPy
reduce
, Python n'est pas souvent nécessaire. Dans la plupart des cas, il existe un moyen plus simple de faire les choses - par exemple, pour enchaîner plusieursor
opérateurs Python , ne pasreduce
termineroperator.or_
, utilisez simplementany
. Et quand il n'y en a pas , il est généralement plus lisible d'utiliser une boucle explicite.Et en fait, NumPy's
any
peut également être utilisé dans ce cas, bien que ce ne soit pas aussi trivial; si vous ne lui donnez pas explicitement un axe, vous vous retrouverez avec un scalaire au lieu d'un tableau. Donc:>>> np.any((x, y, z), axis=0) array([ True, True, True, False], dtype=bool)
Comme vous pouvez vous y attendre,
logical_and
c'est similaire - vous pouvez l'enchaîner,np.reduce
le,functools.reduce
le, ou le remplacerall
par un expliciteaxis
.Qu'en est-il des autres opérations, comme
logical_xor
? Encore une fois, même accord… sauf que dans ce cas, il n'y a pas de fonctionall
/any
-type qui s'applique. (Comment appelleriez-vous celaodd
??)la source
np.logical_or.reduce((x, y, z))
était exactement ce que je cherchais!reduce
n'est plus une fonction interne en python 3. Utilisez plutôt:functools.reduce()
Dans le cas où quelqu'un encore besoin de ce - que vous avez trois tableaux booléens
a
,b
,c
avec la même forme, ce qui donneand
élément par élément:cela donne
or
:c'est ce que tu veux? Empiler beaucoup
logical_and
oulogical_or
n'est pas pratique.la source
Comme les algèbres booléennes sont à la fois commutatives et associatives par définition, les instructions suivantes ou l'équivalent pour les valeurs booléennes de a, b et c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Donc, si vous avez un "ou_logique" qui est dyadique et que vous devez lui passer trois arguments (a, b et c), vous pouvez appeler
logical_or(logical_or(a, b), c)
logical_or(a, logical_or(b, c))
logical_or(c, logical_or(b, a))
ou n'importe quelle permutation que vous aimez.
De retour à python, si vous voulez tester si une condition (générée par une fonction
test
qui prend un testee et renvoie une valeur booléenne) s'applique à a ou b ou c ou à tout élément de la liste L, vous utilisez normalementany(test(x) for x in L)
la source
or
n'est pas vraiment booléenor
, à la fois parce qu'il fonctionne sur des valeurs autres quebool
s (renvoyera
sia
est vrai,b
sinon) et parce qu'il court-circuite (la significationa or b
peut être True, tandis queb or a
déclenche une exception).S'appuyant sur la réponse d'Abarnert pour le cas à n dimensions:
TL; DR:
np.logical_or.reduce(np.array(list))
la source
en utilisant la fonction somme:
a = np.array([True, False, True]) b = array([ False, False, True]) c = np.vstack([a,b,b]) Out[172]: array([[ True, False, True], [False, False, True], [False, False, True]], dtype=bool) np.sum(c,axis=0)>0 Out[173]: array([ True, False, True], dtype=bool)
la source
J'utilise cette solution de contournement qui peut être étendue à n tableaux:
>>> a = np.array([False, True, False, False]) >>> b = np.array([True, False, False, False]) >>> c = np.array([False, False, False, True]) >>> d = (a + b + c > 0) # That's an "or" between multiple arrays >>> d array([ True, True, False, True], dtype=bool)
la source
J'ai essayé les trois méthodes suivantes pour obtenir
logical_and
une liste l de k tableaux de taille n :numpy.logical_and
(voir ci-dessous)numpy.logical_and.reduce(l)
numpy.vstack(l).all(axis=0)
Ensuite, j'ai fait la même chose pour la
logical_or
fonction. Curieusement, la méthode récursive est la plus rapide.import numpy import perfplot def and_recursive(*l): if len(l) == 1: return l[0].astype(bool) elif len(l) == 2: return numpy.logical_and(l[0],l[1]) elif len(l) > 2: return and_recursive(and_recursive(*l[:2]),and_recursive(*l[2:])) def or_recursive(*l): if len(l) == 1: return l[0].astype(bool) elif len(l) == 2: return numpy.logical_or(l[0],l[1]) elif len(l) > 2: return or_recursive(or_recursive(*l[:2]),or_recursive(*l[2:])) def and_reduce(*l): return numpy.logical_and.reduce(l) def or_reduce(*l): return numpy.logical_or.reduce(l) def and_stack(*l): return numpy.vstack(l).all(axis=0) def or_stack(*l): return numpy.vstack(l).any(axis=0) k = 10 # number of arrays to be combined perfplot.plot( setup=lambda n: [numpy.random.choice(a=[False, True], size=n) for j in range(k)], kernels=[ lambda l: and_recursive(*l), lambda l: and_reduce(*l), lambda l: and_stack(*l), lambda l: or_recursive(*l), lambda l: or_reduce(*l), lambda l: or_stack(*l), ], labels = ['and_recursive', 'and_reduce', 'and_stack', 'or_recursive', 'or_reduce', 'or_stack'], n_range=[2 ** j for j in range(20)], logx=True, logy=True, xlabel="len(a)", equality_check=None )
Ci-dessous les performances pour k = 4.
Et voici ci-dessous les performances pour k = 10.
Il semble qu'il y ait un temps système à peu près constant également pour n supérieur.
la source