programing

두 개 이상의 인수에 대한 Numpy '논리적_or'

batch 2023. 8. 24. 21:54
반응형

두 개 이상의 인수에 대한 Numpy '논리적_or'

눔피의logical_or기능을 비교하는 데 필요한 배열은 두 개뿐입니다.두 개 이상의 어레이가 결합되어 있는지 확인하려면 어떻게 해야 합니까?(Numpy의 질문과 관련하여 동일한 질문을 할 수 있습니다.logical_and그리고 두 개 이상의 어레이의 교차점을 얻습니다.)

만약 당신이 질문한다면, 아니요, 문서가 명시적으로 말하는 것처럼, 유일한 매개 변수는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에서 이러한 종류의 체인을 일반화하는 방법은 다음과 같습니다.

>>> 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와는 달리reduce파이썬은 자주 필요하지 않습니다.대부분의 경우 여러 Python을 연결하는 등 보다 간단한 작업 방법이 있습니다.or연산자, 하지 않음reduce위에operator.or_그냥 쓰기any그리고 그것이 없을 때, 일반적으로 명시적 루프를 사용하는 것이 더 읽기 쉽습니다.

그리고 실제로 NumPy도 이 경우에 사용될 수 있습니다. 비록 그렇게 사소한 것은 아니지만요. 만약 여러분이 그것에 축을 명시적으로 지정하지 않는다면, 여러분은 배열 대신 스칼라로 끝날 것입니다.그래서:

>>> np.any((x, y, z), axis=0)
array([ True,  True,  True,  False], dtype=bool)

예상하신 대로 유사합니다. 체인으로 연결할 수 있습니다.np.reduce그것,functools.reduce또는 명시적으로 대체합니다.axis.

다른 사업은 어때요? 다시 말하지만, 같은 거래입니다. 이 경우에는 아무 것도 없습니다.all/any적용되는 -type 함수입니다.(그것을 뭐라고 부를까요?odd?)

누군가 여전히 이것이 필요한 경우 - 3개의 부울 배열이 있다고 가정합니다.a,b,c같은 모양으로, 이것은 줍니다.and요소별:

a * b * c

이것이 주는or:

a + b + c

이게 네가 원하는 거야?많은 양을 쌓아올리기logical_and또는logical_or실용적이지 않습니다.

n차원 사례에 대한 바너트의 답변을 기반으로 구축:

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

부울 대수는 교환적이고 연관적이기 때문에 a, b, c의 부울 값에 대해 다음 문장 또는 동등한 문장을 정의할 수 있습니다.

a or b or c

(a or b) or c

a or (b or c)

(b or a) or c

따라서 만약 당신이 dyadic인 "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))

네가 좋아하는 순열이 무엇이든.


python으로 이 (를, python.test는L의 a bc되며, testee를 사용합니다.

any(test(x) for x in L)

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크기가 n인 k 배열 목록 중 하나:

  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에 대한 성능입니다.

Performances for k=4

다음은 k = 10에 대한 성능입니다.

Performances for k=10

높은 n에 대해서도 대략 일정한 시간 오버헤드가 있는 것으로 보입니다.

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)
a = np.array([True, False, True])
b = np.array([False, False, True])
c = np.array([True, True, True])
d = np.array([True, True, True])

# logical or
lor = (a+b+c+d).astype(bool)

# logical and
land = (a*b*c*d).astype(bool)

다차원 부울 마스크에서 논리적 AND를 수행하기 위해 짧은(최적이 아닐 수 있음) 함수를 사용하려면 다음 재귀 람다 함수를 사용할 수 있습니다.

masks_and = lambda *masks : masks[0] if len(masks) == 1 else masks_and(np.logical_and(masks[0], masks[-1]), *masks[1:-1])
result = masks_and(mask1, mask2, ...)

또한 다음과 같은 개체에 순서가 중요하다고 가정하여 분포 특성(예: 곱셈/AND, 합/OR 등)을 가진 연산자(2개의 인수의 함수)를 적용하기 위한 람다 함수를 일반화할 수 있습니다.

fn2args_reduce = lambda fn2args, *args : args[0] if len(args) == 1 else fn2args_reduce(fn2args, fn2args(args[0], args[1]), *args[2:])
result = fn2args_reduce(np.dot, matrix1, matrix2, ... matrixN)

그것은 당신이 사용하는 것과 같은 결과를 당신에게 줍니다.@ 연산자numpy (으):

np.dot(...(np.dot(np.dot(matrix1, matrix2), matrix3)...), matrixN)

를 들어 를들면입니다.fn2args_reduce(lambda a,b: a+b, 1,2,3,4,5) 훨씬 더인 15개의 숫자를 ).sum이것을 위한 기능, 하지만 나는 그것을 좋아합니다).

N 인수의 함수에 대한 더 일반화된 모델은 다음과 같습니다.

fnNargs_reduce = lambda fnNargs, N, *args : args[0] if len(args) == 1 else fnNargs_reduce(fnNargs, N, fnNargs(*args[:N]), *args[N:])
fnNargs = lambda x1, x2, x3=neutral, ..., xN=neutral: x1 (?) x2 (?) ... (?) xN

여기서 중립은 (?) 연산자에 대한 중립 요소를 의미합니다(예: +의 경우 0, *의 경우 1 등).

왜요? 그냥 재미로 :-)

언급URL : https://stackoverflow.com/questions/20528328/numpy-logical-or-for-more-than-two-arguments

반응형