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


88

Numpy의 logical_or함수는 비교할 배열을 두 개 이상 사용하지 않습니다. 두 개 이상의 배열의 합집합을 어떻게 찾을 수 있습니까? (Numpy logical_and와 두 개 이상의 배열의 교차점에 대해 동일한 질문을 할 수 있습니다 .)



any ()에 대한 분석 방법이 있습니까?
user3074893 dec.

@ user3074893 : 똑같은 문제입니다. 내 대답을 확장할까요?
abarnert

답변:


174

에 대해 묻는 경우 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??)


2
np.logical_or.reduce((x, y, z))내가 찾던 바로 그거야!
blaylockbk

reduce더 이상 파이썬 3의 내부 함수가 아닙니다. 대신 다음을 사용하십시오.functools.reduce()
marvin

10

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

a * b * c

이것은 제공합니다 or:

a + b + c

이것이 당신이 원하는 것입니까? 많이 쌓 logical_and거나 logical_or실용적이지 않습니다.


6

부울 대수는 정의에 따라 교환 및 연관성이 있으므로 다음 문 은 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)

그러나 파이썬은 or정말 부울되지 or는 이외의 값에서 작동 모두 있기 때문에, bool(반환의 a경우 a, truthy입니다 b기타), 그리고 단락 (의미가 있기 때문에 a or b, 진정한 될 수 있지만 b or a인상 예외).
abarnert

@abarnert 감사합니다, 나는 그것을 설명하기 위해 내 대답을 편집했습니다.
Hyperboreus

(사람들이 왜 이것을 반대했는지는 모르겠지만… OP는 그가 "논리적 조건"이라고 부르는 부울 값에 대해 구체적으로 말하는 것 같습니다.)
abarnert

@abarnert 나 한테 묻지마. 나는 당신이 당신의 수학을 (이 경우 부울 대수학) 똑바로 배경에서 똑바로한다면 많은 프로그래밍 문제를 해결하기가 더 쉽다고 생각합니다.
Hyperboreus

4

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

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


4

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)

4

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)

1

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.