Для порівняння logical_or
функції Numpy потрібно не більше двох масивів. Як я можу знайти об'єднання більше двох масивів? (Те саме питання можна поставити стосовно Numpy logical_and
та отримання перетину більше двох масивів.)
Для порівняння logical_or
функції Numpy потрібно не більше двох масивів. Як я можу знайти об'єднання більше двох масивів? (Те саме питання можна поставити стосовно Numpy logical_and
та отримання перетину більше двох масивів.)
Відповіді:
Якщо ви запитуєте про 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)
Але кортеж з трьох однакових масивів однакової довжини є як array_like в термінах NumPy і може використовуватися як 2D масив.
Поза NumPy ви також можете використовувати Python reduce
:
>>> functools.reduce(np.logical_or, (x, y, z))
array([ True, True, True, False], dtype=bool)
Однак, на відміну від NumPy reduce
, Python не часто потрібен. У більшості випадків, є більш простий спосіб зробити що - то, наприклад, в ланцюзі разом кілька Python 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
воно або замінити all
явним axis
.
А як щодо інших операцій, наприклад logical_xor
? Знову ж та сама угода ... за винятком того, що в цьому випадку не застосовується функція all
/ any
-type. (Як би ви це назвали odd
?)
np.logical_or.reduce((x, y, z))
було саме те, що я шукав!
reduce
більше не є внутрішньою функцією в Python 3. Замість того, щоб використовувати:functools.reduce()
Оскільки булеві алгебри є комутативними та асоціативними за визначенням, наступні твердження або еквіваленти для булевих значень a, b і c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Отже, якщо у вас є "логічний_або", який є діадичним, і вам потрібно передати йому три аргументи (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
отримана функцією, яка приймає тестуваного і повертає логічне значення) до a, b або c або до будь-якого елементу списку L, ви зазвичай використовуєте
any(test(x) for x in L)
or
насправді не булевий or
, як тому, що він працює з значеннями, відмінними від bool
s (повертаючи a
if a
є істинним, b
інакше), і тому, що він замикає (значення a or b
може бути True, тоді як b or a
викликає виняток).
Спираючись на відповідь Абарнерта для n-мірного випадку:
TL; DR: np.logical_or.reduce(np.array(list))
Я використовую цей обхідний шлях, який можна розширити до 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)
Я спробував наступні три різні методи для отримання logical_and
списку l з k масивів розміром n :
numpy.logical_and
(див. Нижче)numpy.logical_and.reduce(l)
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 = 10.
Здається, існує приблизно постійний накладний час і для вищих n.
any()
?