Numpy'nin logical_or
işlevi karşılaştırmak için ikiden fazla dizi almaz . İkiden fazla dizinin birleşimini nasıl bulabilirim? (Aynı soru Numpy's logical_and
ve ikiden fazla dizinin kesişiminin elde edilmesi için de sorulabilir .)
Numpy'nin logical_or
işlevi karşılaştırmak için ikiden fazla dizi almaz . İkiden fazla dizinin birleşimini nasıl bulabilirim? (Aynı soru Numpy's logical_and
ve ikiden fazla dizinin kesişiminin elde edilmesi için de sorulabilir .)
Yanıtlar:
Soruyorsanız numpy.logical_or
, o zaman hayır, belgelerin açıkça söylediği gibi, tek parametreler x1, x2
ve isteğe bağlı olarak out
:
numpy.
logical_or
(x1, x2[, out]
) =<ufunc 'logical_or'>
Elbette birden fazla logical_or
aramayı şu şekilde zincirleyebilirsiniz :
>>> 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)
NumPy'de bu tür zincirlemeyi genelleştirmenin yolu şudur reduce
:
>>> np.logical_or.reduce((x, y, z))
array([ True, True, True, False], dtype=bool)
Ve tabii ki bu irade de işin o bunun böyle yürüyor yerine ayrı diziler-aslında bir çok boyutlu dizi varsa demek kullanılacak:
>>> 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)
Ancak, üç eşit uzunlukta 1D dizisinden oluşan bir demet , NumPy terimlerinde bir dizi benzeridir ve bir 2D dizi olarak kullanılabilir.
NumPy dışında, Python'u da kullanabilirsiniz reduce
:
>>> functools.reduce(np.logical_or, (x, y, z))
array([ True, True, True, False], dtype=bool)
Bununla birlikte, NumPy'nin aksine reduce
, Python'a sıklıkla ihtiyaç duyulmaz. Çoğu durumda, zincire işler-örneğin birlikte birden Python yapmak için basit bir yolu var or
operatörleri, yok reduce
üzerinde operator.or_
, sadece kullanmak any
. Ve olmadığında , genellikle açık bir döngü kullanmak daha okunaklı olur.
Aslında NumPy's any
bu durum için de kullanılabilir, ancak o kadar önemsiz olmasa da; Eğer ona açıkça bir eksen vermezseniz, dizi yerine bir skaler elde edersiniz. Yani:
>>> np.any((x, y, z), axis=0)
array([ True, True, True, False], dtype=bool)
Tahmin edebileceğiniz gibi, logical_and
benzer-sizsiniz, o zincir olabilir np.reduce
o functools.reduce
da, veya ikame all
açık olarak axis
.
Peki ya diğer operasyonlar logical_xor
? Yine, aynı anlaşma… bu durumda geçerli olan all
/ any
-type işlevi olmaması dışında . (Sen buna ne diyorsun odd
?)
np.logical_or.reduce((x, y, z))
tam aradığım şeydi!
reduce
artık python 3'te dahili bir işlev değil. Bunun yerine şunu kullanın:functools.reduce()
Boole cebirleri tanım gereği hem değişmeli hem de ilişkisel olduğundan, aşağıdaki ifadeler veya a, b ve c'nin boole değerleri için eşdeğerdir .
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Dolayısıyla, ikili olan bir "mantıksal_veya" varsa ve ona üç bağımsız değişken (a, b ve c) iletmeniz gerekiyorsa,
logical_or(logical_or(a, b), c)
logical_or(a, logical_or(b, c))
logical_or(c, logical_or(b, a))
veya istediğiniz permütasyon.
test
Python'a dönün , bir koşulun (bir test alan ve bir boole değeri döndüren bir işlev tarafından üretilen) a veya b veya c veya L listesinin herhangi bir öğesi için geçerli olup olmadığını test etmek istiyorsanız , normalde kullanırsınız
any(test(x) for x in L)
or
gerçekten boole olmayan or
o dışındaki değerler hem çalışır, çünkü bool
(dönen s a
eğer a
, truthy olduğunu b
aksi) ve kısa devreler (anlam çünkü a or b
, Gerçek olabilirken b or a
artırmalar bir istisna).
Abarnert'in n boyutlu durum için cevabına dayanarak:
TL; DR: np.logical_or.reduce(np.array(list))
N diziye genişletilebilen bu geçici çözümü kullanıyorum:
>>> 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)
Ben almak için aşağıdaki üç farklı yöntem denedim logical_and
bir liste l içinde k boyutu diziler n :
numpy.logical_and
(aşağıya bakın)numpy.logical_and.reduce(l)
numpy.vstack(l).all(axis=0)
Sonra aynısını logical_or
işlev için yaptım . Şaşırtıcı bir şekilde, yinelemeli yöntem en hızlı olanıdır.
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
)
Burada k = 4 için performansların altında.
Ve burada k = 10 için performansların altında.
Görünüşe göre daha yüksek n için de yaklaşık olarak sabit bir zaman ek yükü var.
any()
?