ตัวเลข "logical_or" สำหรับอาร์กิวเมนต์มากกว่าสองอาร์กิวเมนต์


91

logical_orฟังก์ชันของ Numpy ใช้อาร์เรย์ไม่เกินสองอาร์เรย์ในการเปรียบเทียบ ฉันจะหาการรวมกันของอาร์เรย์มากกว่าสองอาร์เรย์ได้อย่างไร (คำถามเดียวกันนี้สามารถถามได้เกี่ยวกับ Numpy logical_andและการได้รับจุดตัดของอาร์เรย์มากกว่าสองอาร์เรย์)


5
any()เหรอ?
karthikr

มีวิธีการวิเคราะห์ใด ๆ กับ () หรือไม่?
user3074893

@ user3074893: มันเหมือนกันทุกประการ คุณต้องการให้ฉันขยายคำตอบ?
abarnert

คำตอบ:


180

หากคุณกำลังถามเกี่ยวกับnumpy.logical_orไม่อย่างที่เอกสารกล่าวอย่างชัดเจนพารามิเตอร์เดียวคือx1, x2และเป็นทางเลือกout:

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


แน่นอนคุณสามารถเชื่อมโยงการlogical_orโทรหลายสายเข้าด้วยกันเช่นนี้:

>>> 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 คือreduce:

>>> np.logical_or.reduce((x, y, z))
array([ True,  True,  True,  False], dtype=bool)

และแน่นอนนี้จะทำงานถ้าคุณมีอาร์เรย์หนึ่งหลายมิติแทนการแยกต่างหากอาร์เรย์ในความเป็นจริงที่ว่ามันหมายถึงการที่จะใช้:

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

แต่ทูเพิลของอาร์เรย์ 1D ที่มีความยาวเท่ากันสามอาร์เรย์นั้นเป็นarray_likeในแง่ NumPy และสามารถใช้เป็นอาร์เรย์ 2D ได้


นอกจาก NumPy คุณยังสามารถใช้ Python's reduce:

>>> functools.reduce(np.logical_or, (x, y, z))
array([ True,  True,  True,  False], dtype=bool)

อย่างไรก็ตามไม่เหมือนกับ NumPy ของreducePython มักไม่จำเป็น สำหรับกรณีส่วนใหญ่มีวิธีที่ง่ายที่จะทำสิ่ง-เช่นโซ่กันหลามหลายorผู้ประกอบการไม่ได้reduceมากกว่าการใช้เพียงoperator.or_ anyและเมื่อไม่มีก็มักจะอ่านได้ง่ายกว่าที่จะใช้การวนซ้ำอย่างชัดเจน

และในความเป็นจริง NumPy anyสามารถใช้กับกรณีนี้ได้เช่นกันแม้ว่าจะไม่เป็นเรื่องเล็กน้อย ถ้าคุณไม่ระบุแกนอย่างชัดเจนคุณจะจบลงด้วยสเกลาร์แทนอาร์เรย์ ดังนั้น:

>>> np.any((x, y, z), axis=0)
array([ True,  True,  True,  False], dtype=bool)

ในขณะที่คุณอาจคาดหวังlogical_andจะคล้ายคุณสามารถโซ่มันnp.reduceมันfunctools.reduceมันหรือทดแทนที่มีอย่างชัดเจนallaxis

สิ่งที่เกี่ยวกับการดำเนินการอื่น ๆ เช่นlogical_xor? อีกครั้งข้อตกลงเดียวกัน ... ยกเว้นว่าในกรณีนี้จะไม่มีฟังก์ชันall/ any-type ที่ใช้ (คุณจะเรียกมันว่าอะไรodd?)


3
np.logical_or.reduce((x, y, z))เป็นเพียงสิ่งที่ฉันกำลังมองหา!
blaylockbk

reduceไม่ใช่ฟังก์ชันภายในใน python 3 อีกต่อไปให้ใช้:functools.reduce()
marvin

10

ในกรณีที่มีคนยังคงต้องนี้ - พูดคุณมีสามอาร์เรย์แบบบูลa, b, cที่มีรูปร่างเหมือนกันนี้จะช่วยให้andองค์ประกอบที่ชาญฉลาด:

a * b * c

สิ่งนี้ให้or:

a + b + c

นี่คือสิ่งที่คุณต้องการหรือไม่? ซ้อนกันมากlogical_andหรือlogical_orไม่สามารถใช้งานได้จริง


6

เนื่องจากอัลเจอร์บราแบบบูลีนมีทั้งแบบสับเปลี่ยนและเชื่อมโยงตามคำจำกัดความข้อความต่อไปนี้หรือเทียบเท่าสำหรับค่าบูลีนของ a, b และ c

a or b or c

(a or b) or c

a or (b or c)

(b or a) or c

ดังนั้นหากคุณมี "logical_or" ซึ่งเป็น dyadic และคุณต้องส่งผ่านอาร์กิวเมนต์สามตัว (a, b และ c) คุณสามารถเรียก

logical_or(logical_or(a, b), c)

logical_or(a, logical_or(b, c))

logical_or(c, logical_or(b, a))

หรือการเปลี่ยนแปลงใด ๆ ที่คุณต้องการ


กลับไปที่ python หากคุณต้องการทดสอบว่าเงื่อนไข (ที่ให้ผลโดยฟังก์ชันtestที่รับ testee และส่งกลับค่าบูลีน) ใช้กับ a หรือ b หรือ c หรือองค์ประกอบใด ๆ ของรายการ L คุณจะใช้ตามปกติ

any(test(x) for x in L)

แต่ Python orไม่ได้เป็นบูลีนจริงๆorทั้งคู่เพราะมันทำงานกับค่าอื่นที่ไม่ใช่bools (ส่งคืนaถ้าaเป็นจริงไม่bเช่นนั้น) และเนื่องจากมันลัดวงจร (ความหมายa or bอาจเป็นจริงในขณะที่b or aมีข้อยกเว้น)
ยกเลิก

@abarnert ขอบคุณฉันได้แก้ไขคำตอบของฉันสำหรับบัญชีนั้นแล้ว
Hyperboreus

(ฉันไม่แน่ใจว่าทำไมคนถึงโหวตเรื่องนี้ แต่ ... OP ดูเหมือนจะพูดถึงค่าบูลีนโดยเฉพาะซึ่งเขาเรียกว่า "เงื่อนไขทางตรรกะ")
ยกเลิก

@abarnert ไม่ต้องถามฉัน. ฉันมีความเห็นว่าหากคุณเข้าใจคณิตศาสตร์ของคุณตรง (ในกรณีนี้อัลเกบราสบูลีน) อยู่เบื้องหลังปัญหาการเขียนโปรแกรมจำนวนมากจะแก้ได้ง่ายกว่า
Hyperboreus


4

โดยใช้ฟังก์ชัน sum:

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 อาร์เรย์:

>>> 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

ฉันได้ลองสามวิธีต่อไปนี้เพื่อรับlogical_andรายการlของkอาร์เรย์ขนาดn :

  1. การใช้การเรียกซ้ำnumpy.logical_and(ดูด้านล่าง)
  2. การใช้ numpy.logical_and.reduce(l)
  3. การใช้ numpy.vstack(l).all(axis=0)

จากนั้นฉันก็ทำเช่นเดียวกันสำหรับlogical_orฟังก์ชัน น่าแปลกที่วิธีการเรียกซ้ำเป็นวิธีที่เร็วที่สุด

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
)

ด้านล่างการแสดงสำหรับ k = 4

การแสดงสำหรับ k = 4

และด้านล่างการแสดงสำหรับ k = 10

การแสดงสำหรับ k = 10

ดูเหมือนว่าจะมีค่าใช้จ่ายเวลาคงที่โดยประมาณสำหรับ n ที่สูงขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.