logical_orHàm của Numpy không cần nhiều hơn hai mảng để so sánh. Làm cách nào để tìm hợp nhất của nhiều hơn hai mảng? (Câu hỏi tương tự có thể được đặt ra liên quan đến Numpy's logical_andvà lấy giao điểm của nhiều hơn hai mảng.)
logical_orHàm của Numpy không cần nhiều hơn hai mảng để so sánh. Làm cách nào để tìm hợp nhất của nhiều hơn hai mảng? (Câu hỏi tương tự có thể được đặt ra liên quan đến Numpy's logical_andvà lấy giao điểm của nhiều hơn hai mảng.)
Câu trả lời:
Nếu bạn đang hỏi về numpy.logical_or, thì không, như tài liệu nói rõ ràng, các tham số duy nhất là x1, x2và tùy chọn out:
numpy.logical_or(x1, x2[, out]) =<ufunc 'logical_or'>
Tất nhiên, bạn có thể xâu chuỗi nhiều logical_orcuộc gọi lại với nhau như thế này:
>>> 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)
Cách tổng quát hóa loại chuỗi này trong NumPy là với reduce:
>>> np.logical_or.reduce((x, y, z))
array([ True, True, True, False], dtype=bool)
Và tất nhiên điều này cũng sẽ làm việc nếu bạn có một mảng đa chiều thay vì mảng trong thực tế riêng biệt, đó là cách nó có nghĩa là để được sử dụng:
>>> 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)
Nhưng một bộ ba mảng 1D có độ dài bằng nhau là một mảng_như theo thuật ngữ NumPy và có thể được sử dụng như một mảng 2D.
Ngoài NumPy, bạn cũng có thể sử dụng Python reduce:
>>> functools.reduce(np.logical_or, (x, y, z))
array([ True, True, True, False], dtype=bool)
Tuy nhiên, không giống như NumPy's reduce, Python không thường xuyên cần thiết. Đối với hầu hết các trường hợp, có một cách đơn giản hơn để thực hiện mọi việc — ví dụ: chuỗi nhiều ortoán tử Python lại với nhau , đừng reducekết thúc operator.or_, chỉ cần sử dụng any. Và khi có không phải là , nó thường dễ đọc hơn để sử dụng một vòng lặp rõ ràng.
Và trên thực tế, NumPy's anycũng có thể được sử dụng cho trường hợp này, mặc dù nó không quá tầm thường; nếu bạn không cung cấp cho nó một trục rõ ràng, bạn sẽ kết thúc với một đại lượng vô hướng thay vì một mảng. Vì thế:
>>> np.any((x, y, z), axis=0)
array([ True, True, True, False], dtype=bool)
Như bạn có thể mong đợi, logical_andcũng tương tự — bạn có thể xâu chuỗi nó, np.reducenó, functools.reducenó, hoặc thay thế allbằng một cách rõ ràng axis.
Điều gì về các hoạt động khác, như thế logical_xornào? Một lần nữa, cùng một thỏa thuận… ngoại trừ trường hợp này không có hàm all/ any-type nào được áp dụng. (Bạn sẽ gọi nó là gì odd?)
np.logical_or.reduce((x, y, z))chỉ là những gì tôi đang tìm kiếm!
reducekhông còn là một hàm nội bộ trong python 3. Thay vào đó, hãy sử dụng:functools.reduce()
Vì đại số boolean là cả giao hoán và kết hợp theo định nghĩa, các câu lệnh sau đây hoặc tương đương cho các giá trị boolean của a, b và c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Vì vậy, nếu bạn có "logic_or" là dyadic và bạn cần chuyển cho nó ba đối số (a, b và c), bạn có thể gọi
logical_or(logical_or(a, b), c)
logical_or(a, logical_or(b, c))
logical_or(c, logical_or(b, a))
hoặc bất kỳ phép hoán vị nào bạn thích.
Quay lại python, nếu bạn muốn kiểm tra xem một điều kiện (được tạo ra bởi một hàm testnhận testee và trả về giá trị boolean) có áp dụng cho a hoặc b hoặc c hoặc bất kỳ phần tử nào của danh sách L hay không, bạn thường sử dụng
any(test(x) for x in L)
orkhông thực sự là boolean or, cả vì nó hoạt động trên các giá trị khác với bools (trả về anếu alà true, bngược lại) và vì nó ngắn mạch (nghĩa a or bcó thể là True, trong khi b or atạo ra một ngoại lệ).
Dựa trên câu trả lời của abarnert cho trường hợp n chiều:
TL; DR: np.logical_or.reduce(np.array(list))
Tôi sử dụng cách giải quyết này có thể được mở rộng cho n mảng:
>>> 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)
Tôi đã thử ba phương pháp khác nhau sau đây để lấy logical_anddanh sách l gồm k mảng có kích thước n :
numpy.logical_and(xem bên dưới)numpy.logical_and.reduce(l)numpy.vstack(l).all(axis=0)Sau đó, tôi đã làm tương tự cho logical_orchức năng. Đáng ngạc nhiên là phương pháp đệ quy là phương pháp nhanh nhất.
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
)
Dưới đây là các biểu diễn cho k = 4.
Và ở đây bên dưới biểu diễn cho k = 10.
Có vẻ như cũng có một khoảng thời gian không đổi gần như không đổi đối với n cao hơn.
any()?