Функция Numpy logical_orтребует для сравнения не более двух массивов. Как найти объединение более двух массивов? (Тот же вопрос можно задать относительно Numpy logical_andи получения пересечения более чем двух массивов.)
Способ обобщения такого рода цепочек в NumPy - это reduce :
>>> np.logical_or.reduce((x, y, z))
array([ True, True, True, False], dtype=bool)
И, конечно, это также будет работать, если у вас есть один многомерный массив вместо отдельных массивов - на самом деле, именно так он должен использоваться:
Однако, в отличие от NumPy reduce, Python не часто нужен. В большинстве случаев есть более простой способ сделать что-то - например, связать вместе несколько orоператоров Python , не reduceпереусердствуйте operator.or_, просто используйтеany . А когда его нет , обычно удобнее использовать явный цикл.
И на самом деле NumPy anyможно использовать и в этом случае, хотя это не так тривиально; если вы явно не укажете ему ось, вы получите скаляр вместо массива. Так:
Как и следовало ожидать, logical_andон похож - вы можете связать его, np.reduceоно, functools.reduceоно или заменить allявным axis.
А как насчет других операций, например logical_xor? Опять же, то же самое ... за исключением того, что в этом случае нет функции all/ any-типа, которая применяется. (Как бы вы это назвали odd?)
Поскольку булевы алгебры являются коммутативными и ассоциативными по определению, следующие утверждения или их эквиваленты для булевых значений a, b и c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Итак, если у вас есть "logic_or", который является диадическим, и вам нужно передать ему три аргумента (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, вы обычно используете
Но Python на orсамом деле не является логическим orкак потому, что он работает со значениями, отличными от bools (возвращение, aесли aистинно, в bпротивном случае), так и потому, что он закорачивает (это a or bможет быть True, а b or aвызывает исключение).
abarnert
@abarnert Спасибо, я отредактировал свой ответ, чтобы учесть это.
Hyperboreus
(Я не уверен, почему люди проголосовали против этого, однако… OP, похоже, конкретно говорит о логических значениях, которые он называет «логическими условиями».)
abarnert
@abarnert Не спрашивай меня. Я считаю, что если вы разберетесь с математикой (в данном случае с булевыми алгебрами) на заднем плане, многие проблемы программирования будет легче решить.
Hyperboreus
4
Основываясь на ответе Абарнерта для n-мерного случая:
Я использую этот обходной путь, который можно расширить до 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)
any()
?Ответы:
Если вы спрашиваете
numpy.logical_or
, то нет, как прямо говорится в документации, единственными параметрами являютсяx1, x2
, и необязательноout
:Конечно, вы можете объединить несколько
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)
Но набор из трех одномерных массивов одинаковой длины является в терминах NumPy array_like и может использоваться как двухмерный массив.
Вне NumPy вы также можете использовать Python
reduce
:>>> functools.reduce(np.logical_or, (x, y, z)) array([ True, True, True, False], dtype=bool)
Однако, в отличие от NumPy
reduce
, Python не часто нужен. В большинстве случаев есть более простой способ сделать что-то - например, связать вместе несколькоor
операторов Python , не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
-типа, которая применяется. (Как бы вы это назвалиodd
?)источник
np.logical_or.reduce((x, y, z))
было именно то, что я искал!reduce
больше не является внутренней функцией в python 3. Вместо этого используйте:functools.reduce()
В случае , если кто - то все - таки нужно это - у вас есть три логических массивов
a
,b
,c
с одной и той же формы, что даетand
поэлементно:это дает
or
:Это то, что вы хотите? Укладывать много
logical_and
илиlogical_or
нецелесообразно.источник
Поскольку булевы алгебры являются коммутативными и ассоциативными по определению, следующие утверждения или их эквиваленты для булевых значений a, b и c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Итак, если у вас есть "logic_or", который является диадическим, и вам нужно передать ему три аргумента (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
еслиa
истинно, вb
противном случае), так и потому, что он закорачивает (этоa or b
может быть True, аb or a
вызывает исключение).Основываясь на ответе Абарнерта для n-мерного случая:
TL; DR:
np.logical_or.reduce(np.array(list))
источник
используя функцию суммы:
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)
источник
Я использую этот обходной путь, который можно расширить до 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 существуют приблизительно постоянные накладные расходы по времени.
источник