logical_or
Funkcja Numpy'ego wymaga do porównania nie więcej niż dwóch tablic. Jak znaleźć sumę więcej niż dwóch tablic? (To samo pytanie można zadać w odniesieniu do Numpy'ego logical_and
i uzyskania przecięcia więcej niż dwóch tablic).
88
any()
?Odpowiedzi:
Jeśli o to pytasz
numpy.logical_or
, to nie, jak wyraźnie mówią dokumenty, jedynymi parametrami sąx1, x2
i opcjonalnieout
:Możesz oczywiście łączyć wiele
logical_or
połączeń w ten sposób:>>> 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)
Sposób na uogólnienie tego rodzaju łańcuchów w NumPy jest następujący
reduce
:>>> np.logical_or.reduce((x, y, z)) array([ True, True, True, False], dtype=bool)
I oczywiście to będzie również działać, jeśli masz jeden wielowymiarową tablicę zamiast oddzielnych tablic-w rzeczywistości, to w jaki sposób to oznaczało być stosowane:
>>> 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)
Ale krotka trzech tablic 1D o równej długości jest tablicą podobną do tablicy w terminach NumPy i może być używana jako tablica 2D.
Poza NumPy możesz także używać Pythona
reduce
:>>> functools.reduce(np.logical_or, (x, y, z)) array([ True, True, True, False], dtype=bool)
Jednak w przeciwieństwie do NumPy
reduce
, Python nie jest często potrzebny. W większości przypadków istnieje prostszy sposób wykonywania pewnych czynności - np. Łączenie wieluor
operatorów Pythona w łańcuch , niereduce
przerywajoperator.or_
, po prostu użyjany
. A jeśli nie ma , zwykle bardziej czytelne jest użycie jawnej pętli.W rzeczywistości NumPy
any
może być również używany w tym przypadku, chociaż nie jest to aż tak trywialne; jeśli jawnie nie nadasz mu osi, otrzymasz skalar zamiast tablicy. Więc:>>> np.any((x, y, z), axis=0) array([ True, True, True, False], dtype=bool)
Jak można się spodziewać,
logical_and
jest podobnie - można to połączyć w łańcuch,np.reduce
to,functools.reduce
to lub zamienićall
na jawneaxis
.A co z innymi operacjami
logical_xor
? Ponownie, ta sama umowa… z tym wyjątkiem, że w tym przypadku nie ma zastosowania funkcjiall
/any
-type. (Jak byś to nazwałodd
?)źródło
np.logical_or.reduce((x, y, z))
był właśnie tym, czego szukałem!reduce
nie jest już funkcją wewnętrzną w Pythonie 3. Zamiast tego użyj:functools.reduce()
W przypadku gdy ktoś nadal potrzebujemy tego - powiedzmy masz trzy tablice logiczne
a
,b
,c
z takim samym kształcie, co dajeand
element mądry:to daje
or
:Czy to jest to, czego chcesz? Układanie w stos dużo
logical_and
lublogical_or
nie jest praktyczne.źródło
Ponieważ algebry boolowskie są z definicji przemienne i asocjacyjne, poniższe instrukcje lub ich odpowiedniki dla wartości boolowskich a, b i c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Więc jeśli masz „logical_or”, który jest diadyczny i musisz przekazać mu trzy argumenty (a, b i c), możesz wywołać
logical_or(logical_or(a, b), c)
logical_or(a, logical_or(b, c))
logical_or(c, logical_or(b, a))
lub jakąkolwiek permutację lubisz.
Wracając do Pythona, jeśli chcesz sprawdzić, czy warunek (uzyskany przez funkcję,
test
która przyjmuje testowanego i zwraca wartość logiczną) ma zastosowanie do a, b lub c lub dowolnego elementu listy L, zwykle używaszany(test(x) for x in L)
źródło
or
nie jest tak naprawdę logicznyor
, zarówno dlatego, że działa na wartościach innych niżbool
s (zwraca,a
jeślia
jest prawdą, wb
przeciwnym razie), i dlatego, że powoduje zwarcia (co oznacza, żea or b
może być True, podczas gdyb or a
zgłasza wyjątek).Opierając się na odpowiedzi abarnerta dla przypadku n-wymiarowego:
TL; DR:
np.logical_or.reduce(np.array(list))
źródło
używając funkcji sumy:
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)
źródło
Używam tego obejścia, które można rozszerzyć do n tablic:
>>> 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)
źródło
Wypróbowałem następujące trzy różne metody, aby uzyskać
logical_and
listę l z k tablic o rozmiarze n :numpy.logical_and
(patrz poniżej)numpy.logical_and.reduce(l)
numpy.vstack(l).all(axis=0)
Następnie zrobiłem to samo dla
logical_or
funkcji. O dziwo, metoda rekurencyjna jest najszybsza.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 )
Poniżej wyniki dla k = 4.
A poniżej wyniki dla k = 10.
Wydaje się, że istnieje w przybliżeniu stały narzut czasowy również dla wyższego n.
źródło