Функция Numpy logical_or
требует для сравнения не более двух массивов. Как найти объединение более двух массивов? (Тот же вопрос можно задать относительно Numpy logical_and
и получения пересечения более чем двух массивов.)
Функция Numpy logical_or
требует для сравнения не более двух массивов. Как найти объединение более двух массивов? (Тот же вопрос можно задать относительно 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)
Но набор из трех одномерных массивов одинаковой длины является в терминах 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.
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))
Я использую этот обходной путь, который можно расширить до 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()
?