İkiden fazla bağımsız değişken için numpy "mantıksal_veya"


90

Numpy'nin logical_orişlevi karşılaştırmak için ikiden fazla dizi almaz . İkiden fazla dizinin birleşimini nasıl bulabilirim? (Aynı soru Numpy's logical_andve ikiden fazla dizinin kesişiminin elde edilmesi için de sorulabilir .)



herhangi bir () için analagöz bir yol var mı?
user3074893

@ user3074893: Bu tamamen aynı sorun. Cevabımı genişletmemi mi istiyorsun?
abarnert

Yanıtlar:


180

Soruyorsanız numpy.logical_or, o zaman hayır, belgelerin açıkça söylediği gibi, tek parametreler x1, x2ve isteğe bağlı olarak out:

numpy.logical_or( x1, x2[, out]) =<ufunc 'logical_or'>


Elbette birden fazla logical_oraramayı ş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 oroperatö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 anybu 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_andbenzer-sizsiniz, o zincir olabilir np.reduceo functools.reduceda, veya ikame allaçı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?)


3
np.logical_or.reduce((x, y, z))tam aradığım şeydi!
blaylockbk

reduceartık python 3'te dahili bir işlev değil. Bunun yerine şunu kullanın:functools.reduce()
marvin

10

Eğer üç Boole diziler var Say - durumda birileri hala bu ihtiyaç a, b, caynı şekli ile, bu verir and: öğeye göre

a * b * c

bu şunu verir or:

a + b + c

İstediğiniz bu mu? Çok fazla istiflemek logical_andya logical_orda pratik değildir.


6

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.


testPython'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)

Ama Python orgerçekten boole olmayan oro dışındaki değerler hem çalışır, çünkü bool(dönen s aeğer a, truthy olduğunu baksi) ve kısa devreler (anlam çünkü a or b, Gerçek olabilirken b or aartırmalar bir istisna).
abarnert

@abarnert Teşekkürler, cevabımı bunun için düzenledim.
Hyperboreus

(İnsanların buna neden olumsuz oy verdiklerinden emin değilim, ancak ... OP, özellikle "mantıksal koşullar" olarak adlandırdığı boole değerlerinden bahsediyor gibi görünüyor.)
abarnert

@abarnert Bana sorma. Arka planda matematiğinizi doğru bir şekilde alırsanız (bu durumda boole cebirleri), birçok programlama sorununun çözülmesinin daha kolay olacağı kanısındayım.
Hyperboreus

5

Abarnert'in n boyutlu durum için cevabına dayanarak:

TL; DR: np.logical_or.reduce(np.array(list))


4

toplam işlevini kullanarak:

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)

4

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)

2

Ben almak için aşağıdaki üç farklı yöntem denedim logical_andbir liste l içinde k boyutu diziler n :

  1. Özyinelemeli kullanma numpy.logical_and(aşağıya bakın)
  2. Kullanma numpy.logical_and.reduce(l)
  3. Kullanma numpy.vstack(l).all(axis=0)

Sonra aynısını logical_oriş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.

K = 4 için performanslar

Ve burada k = 10 için performansların altında.

K = 10 için performanslar

Görünüşe göre daha yüksek n için de yaklaşık olarak sabit bir zaman ek yükü var.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.