Die logical_or
Funktion von Numpy benötigt nicht mehr als zwei Arrays zum Vergleichen. Wie kann ich die Vereinigung von mehr als zwei Arrays finden? (Dieselbe Frage könnte in Bezug auf Numpys logical_and
und den Schnittpunkt von mehr als zwei Arrays gestellt werden.)
87
any()
?Antworten:
Wenn Sie nachfragen
numpy.logical_or
, dann nein, wie in den Dokumenten ausdrücklich angegeben, sind die einzigen Parameterx1, x2
und optionalout
:Sie können natürlich mehrere
logical_or
Anrufe wie folgt verketten:>>> 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)
Die Art und Weise, diese Art der Verkettung in NumPy zu verallgemeinern, ist mit
reduce
:>>> np.logical_or.reduce((x, y, z)) array([ True, True, True, False], dtype=bool)
Und natürlich wird dies auch arbeiten , wenn Sie ein mehrdimensionales Array statt separater Arrays in der Tat, das ist , wie es gemeint verwendet werden:
>>> 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)
Ein Tupel aus drei 1D-Arrays gleicher Länge ist jedoch in NumPy-Begriffen array_like und kann als 2D-Array verwendet werden.
Außerhalb von NumPy können Sie auch Pythons verwenden
reduce
:>>> functools.reduce(np.logical_or, (x, y, z)) array([ True, True, True, False], dtype=bool)
Im Gegensatz zu NumPy's
reduce
wird Python jedoch nicht oft benötigt. In den meisten Fällen gibt es eine einfachere Möglichkeit, Dinge zu tun - z. B. mehrere Python-or
Operatoren miteinander zu verketten , nicht zureduce
Ende zu gehenoperator.or_
, sondern nur zu verwendenany
. Und wenn dies nicht der Fall ist , ist es normalerweise besser lesbar, eine explizite Schleife zu verwenden.Tatsächlich kann NumPy's
any
auch für diesen Fall verwendet werden, obwohl es nicht ganz so trivial ist. Wenn Sie ihm keine Achse explizit zuweisen, erhalten Sie einen Skalar anstelle eines Arrays. Damit:>>> np.any((x, y, z), axis=0) array([ True, True, True, False], dtype=bool)
Wie zu erwarten ist,
logical_and
ist es ähnlich - Sie können es verketten,np.reduce
es,functools.reduce
es oderall
durch ein explizites ersetzenaxis
.Was ist mit anderen Operationen
logical_xor
? Wieder das gleiche Geschäft ... außer dass in diesem Fall keineall
/any
-Typ-Funktion gilt. (Wie würdest du es nennenodd
?)quelle
np.logical_or.reduce((x, y, z))
war genau das, wonach ich gesucht habe!reduce
ist keine interne Funktion mehr in Python 3. Verwenden Sie stattdessen:functools.reduce()
Im Fall , dass jemand noch diese - sagen Sie drei Boolesche Arrays
a
,b
,c
mit der gleichen Form, das gibtand
elementweise:das gibt
or
:Ist das was du willst? Viel zu stapeln
logical_and
oderlogical_or
ist nicht praktikabel.quelle
Da boolesche Algebren per Definition sowohl kommutativ als auch assoziativ sind, gelten die folgenden Aussagen oder Äquivalente für boolesche Werte von a, b und c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Wenn Sie also ein "logisches_oder" haben, das dyadisch ist und drei Argumente (a, b und c) übergeben muss, können Sie es aufrufen
logical_or(logical_or(a, b), c)
logical_or(a, logical_or(b, c))
logical_or(c, logical_or(b, a))
oder welche Permutation du magst.
Zurück zu Python: Wenn Sie testen möchten, ob eine Bedingung (die von einer Funktion erhalten wird
test
, die einen Testempfänger akzeptiert und einen booleschen Wert zurückgibt) für a oder b oder c oder ein Element der Liste L gilt, verwenden Sie normalerweiseany(test(x) for x in L)
quelle
or
ist nicht wirklich booleschor
, sowohl weil es mit anderen Werten alsbool
s arbeitet (Rückgabe,a
wenna
es wahr ist,b
sonst), als auch weil es kurzschließt (was bedeutet,a or b
dass es wahr ist, währendb or a
eine Ausnahme ausgelöst wird ).Aufbauend auf abargerts Antwort für den n-dimensionalen Fall:
TL; DR:
np.logical_or.reduce(np.array(list))
quelle
mit der Summenfunktion:
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)
quelle
Ich verwende diese Problemumgehung, die auf n Arrays erweitert werden kann:
>>> 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)
quelle
Ich habe die folgenden drei verschiedenen Methoden versucht , die erhalten
logical_and
eine Liste l von k - Arrays der Größe n :numpy.logical_and
(siehe unten)numpy.logical_and.reduce(l)
numpy.vstack(l).all(axis=0)
Dann habe ich dasselbe für die
logical_or
Funktion gemacht. Überraschenderweise ist die rekursive Methode die schnellste.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 )
Hier unten die Leistungen für k = 4.
Und hier unten die Leistungen für k = 10.
Es scheint, dass es auch für höheres n einen annähernd konstanten Zeitaufwand gibt.
quelle