[python] 두 개 이상의 인수에 대한 Numpy`logical_or`

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)

그러나 3 개의 동일한 길이 1D 배열의 튜플은 NumPy 용어 로 array_like 이며 2D 배열로 사용할 수 있습니다.


NumPy 외부에서 Python의 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그것을, 또는 대신 all명시 적으로 axis.

같은 다른 작업은 logical_xor어떻습니까? 다시, 동일한 거래…이 경우 적용되는 all/ any유형 기능 이 없다는 점만 제외하면 . (무엇이라고 부르겠습니까 odd??)


답변

세 개의 부울 배열을 가지고 말 – 경우 누군가가 여전히 필요 a, b, c같은 모양으로,이 제공 and: 요소 현명한

a * b * c

이것은 제공합니다 or:

a + b + c

이것이 당신이 원하는 것입니까? 많이 쌓 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

따라서 이원적인 “logical_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))

또는 원하는 순열.


파이썬으로 돌아가서 조건 (테스트 대상 test을 취하고 부울 값을 반환하는 함수에 의해 생성됨)이 a, b 또는 c 또는 목록 L의 요소에 적용 되는지 테스트 하려면 일반적으로 사용합니다.

any(test(x) for x in L)


답변

n 차원 사례에 대한 abarnert의 답변을 기반으로 작성 :

TL; DR : np.logical_or.reduce(np.array(list))


답변

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)


답변

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)


답변

다음 세 가지 방법을 시도하여 n 크기 의 k 배열 logical_and목록 l 을 가져 왔습니다 .

  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에 대해서도 거의 일정한 시간 오버 헤드가있는 것 같습니다.