Fungsi Numpy logical_or
tidak membutuhkan lebih dari dua array untuk dibandingkan. Bagaimana saya bisa menemukan gabungan lebih dari dua array? (Pertanyaan yang sama dapat ditanyakan berkenaan dengan Numpy logical_and
dan mendapatkan persimpangan lebih dari dua larik.)
90
any()
?Jawaban:
Jika Anda bertanya tentang
numpy.logical_or
, maka tidak, seperti yang dikatakan dokumen secara eksplisit, satu-satunya parameter adalahx1, x2
, dan secara opsionalout
:Anda tentu saja dapat menyatukan beberapa
logical_or
panggilan seperti ini:>>> 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)
Cara untuk menggeneralisasi rangkaian jenis ini di NumPy adalah dengan
reduce
:>>> np.logical_or.reduce((x, y, z)) array([ True, True, True, False], dtype=bool)
Dan tentu saja ini juga akan berfungsi jika Anda memiliki satu larik multi-dimensi, bukan larik terpisah — faktanya, begitulah maksud penggunaannya:
>>> 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)
Tapi tuple dari tiga array 1D yang sama panjangnya adalah array_like dalam istilah NumPy, dan dapat digunakan sebagai array 2D.
Di luar NumPy, Anda juga dapat menggunakan Python
reduce
:>>> functools.reduce(np.logical_or, (x, y, z)) array([ True, True, True, False], dtype=bool)
Namun, tidak seperti NumPy
reduce
, Python tidak sering dibutuhkan. Untuk kebanyakan kasus, ada cara yang lebih sederhana untuk melakukan sesuatu — misalnya, untuk menyatukan beberapaor
operator Python , janganreduce
selesaioperator.or_
, cukup gunakanany
. Dan ketika ada tidak , itu biasanya lebih mudah dibaca menggunakan loop eksplisit.Dan nyatanya NumPy's
any
bisa digunakan untuk kasus ini juga, meski tidak sepele; jika Anda tidak secara eksplisit memberikan sumbu, Anda akan berakhir dengan skalar, bukan array. Begitu:>>> np.any((x, y, z), axis=0) array([ True, True, True, False], dtype=bool)
As you might expect,
logical_and
is similar—you can chain it,np.reduce
it,functools.reduce
it, or substituteall
with an explicitaxis
.What about other operations, like
logical_xor
? Again, same deal… except that in this case there is noall
/any
-type function that applies. (What would you call it?odd
?)sumber
np.logical_or.reduce((x, y, z))
was just what I was looking for!reduce
is no longer an internal function in python 3. Instead use:functools.reduce()
In case someone still need this - Say you have three Boolean arrays
a
,b
,c
with the same shape, this givesand
element-wise:this gives
or
:Is this what you want? Stacking a lot of
logical_and
orlogical_or
is not practical.sumber
As boolean algebras are both commutative and associative by definition, the following statements or equivalent for boolean values of a, b and c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
So if you have a "logical_or" which is dyadic and you need to pass it three arguments (a, b, and c), you can call
logical_or(logical_or(a, b), c)
logical_or(a, logical_or(b, c))
logical_or(c, logical_or(b, a))
or whatever permutation you like.
Back to python, if you want to test whether a condition (yielded by a function
test
that takes a testee and returns a boolean value) applies to a or b or c or any element of list L, you normally useany(test(x) for x in L)
sumber
or
isn't really booleanor
, both because it works on values other thanbool
s (returninga
ifa
is truthy,b
otherwise), and because it short-circuits (meaninga or b
may be True, whileb or a
raises an exception).Building on abarnert's answer for n-dimensional case:
TL;DR:
np.logical_or.reduce(np.array(list))
sumber
using the sum function:
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)
sumber
I use this workaround which can be extended to n arrays:
>>> 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)
sumber
I've tried the following three different methods to get the
logical_and
of a list l of k arrays of size n:numpy.logical_and
(see below)numpy.logical_and.reduce(l)
numpy.vstack(l).all(axis=0)
Then I did the same for the
logical_or
function. Surprisingly enough, the recursive method is the fastest one.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 )
Here below the performances for k = 4.
And here below the performances for k = 10.
It seems that there is an approximately constant time overhead also for higher n.
sumber