numpy 배열의 모든 경계에 0이 있는지 확인하십시오.


13

다차원 numpy 배열에 모든면에 0이 있는지 확인하는 가장 빠른 방법은 무엇입니까?

따라서 간단한 2D 예를 들면 다음과 같습니다.

x = np.random.rand(5, 5)
assert np.sum(x[0:,  0]) == 0
assert np.sum(x[0,  0:]) == 0
assert np.sum(x[0:, -1]) == 0
assert np.sum(x[-1, 0:]) == 0

이것은 2D 사례에는 적합하지만 더 큰 치수를 작성하는 것은 약간 지루한 일이며 효율적이고 유지 관리하기 위해 여기에 사용할 수있는 영리한 수 많은 트릭이 있는지 궁금합니다.


8
np.all (x[:, 0] == 0)합계보다 안전 하지 않습니까? 합계 테스트는 모든 숫자가 양수인 경우에만 정확합니다.
데 미룬


1
@ Demi-Lume 의미가 있습니다. 내 경우에는 모든 것이 0보다 크지 만 귀하의 의견은 높이 평가됩니다 :)
Luca

1
3D의 경우 큐브의면 (6 개가 있음) 또는 모서리 (12 개가 있음)를 의미합니까?
Riccardo Bucco

@RiccardoBucco 그래, 6 얼굴. 그러나 나의 문제는 그것이 3보다 높은 차원으로 갈 수 있다는 것입니다.
Luca

답변:


7

이를 수행하는 방법은 다음과 같습니다.

assert(all(np.all(np.take(x, index, axis=axis) == 0)
           for axis in range(x.ndim)
           for index in (0, -1)))

np.take "팬시"인덱싱과 같은 일을합니다.


1
@Luca : 문서가 명확하지 않지만 numpy.take사본을 만듭니다. 보기에 따라 코드보다 성능이 저하 될 수 있습니다. NumPy보기 효율성이 때때로 이상합니다.
user2357112는

1
@RiccardoBucco : len(x.shape)보다 간단하게 쓸 수 있습니다 x.ndim.
user2357112는

1
@ user2357112supportsMonica 감사합니다, 고쳤습니다 :)
Riccardo Bucco

5
또한리스트 이해 기능을 사용하면 all단락을 방지 할 수 있습니다. 괄호를 제거하여 생성기 표현식을 사용 all하여 단일 numpy.all호출이 리턴 되는 즉시 리턴 할 수 False있습니다.
user2357112는

1
모니카 트루 !!
Riccardo Bucco

5

다음은 실제로 관심있는 배열 부분을 검사하고 전체 배열의 크기로 마스크를 구성하는 데 시간을 낭비하지 않는 대답입니다. 파이썬 수준의 루프가 있지만 배열 크기 대신 차원 수에 비례하여 반복이 짧습니다.

def all_borders_zero(array):
    if not array.ndim:
        raise ValueError("0-dimensional arrays not supported")
    for dim in range(array.ndim):
        view = numpy.moveaxis(array, dim, 0)
        if not (view[0] == 0).all():
            return False
        if not (view[-1] == 0).all():
            return False
    return True

다음과 같은 상황 not (view[0] == 0).all()view[0].any()있습니까?
Paul Panzer

@PaulPanzer : 나도 view[0].any()작동 한다고 생각합니다. 나는 두 가지 옵션과 관련된 캐스팅 및 버퍼링의 효율성 영향을 완전히 확신하지 못합니다. view[0].any()이론적으로 더 빠르게 구현할 수는 있지만 이전에는 이상한 결과를 보았으며 관련된 버퍼링을 완전히 이해하지 못했습니다.
user2357112는 0:05에 Monica

view[0].view(bool).any()고속 솔루션 이라고 생각 합니다.
Paul Panzer


(또한 여부 argmax또는 any일반 제로 불균등 네거티브 제로 처리 부울보기 수단을 사용.)
user2357112 모니카 지원

2

나는 배열을 재구성 한 다음 반복했습니다. 불행히도, 내 대답은 적어도 3 차원이 있다고 가정하고 일반 행렬에 대해 오류가 발생한다고 가정하면 1 차원 및 2 차원 모양 배열에 대한 특수 절을 추가해야합니다. 또한 속도가 느려서 더 나은 솔루션이있을 수 있습니다.

x = np.array(
        [
            [
                [0 , 1, 1, 0],
                [0 , 2, 3, 0],
                [0 , 4, 5, 0]
            ],
            [
                [0 , 6, 7, 0],
                [0 , 7, 8, 0],
                [0 , 9, 5, 0]
            ]
        ])

xx = np.array(
        [
            [
                [0 , 0, 0, 0],
                [0 , 2, 3, 0],
                [0 , 0, 0, 0]
            ],
            [
                [0 , 0, 0, 0],
                [0 , 7, 8, 0],
                [0 , 0, 0, 0]
            ]
        ])

def check_edges(x):

    idx = x.shape
    chunk = np.prod(idx[:-2])
    x = x.reshape((chunk*idx[-2], idx[-1]))
    for block in range(chunk):
        z = x[block*idx[-2]:(block+1)*idx[-2], :]
        if not np.all(z[:, 0] == 0):
            return False
        if not np.all(z[:, -1] == 0):
            return False
        if not np.all(z[0, :] == 0):
            return False
        if not np.all(z[-1, :] == 0):
            return False

    return True

어떤 생산

>>> False
>>> True

기본적으로 모든 치수를 서로 쌓은 다음 가장자리를 확인하기 위해 치수를 살펴 봅니다.


배열의 잘못된 부분을 검사합니다. 3 차원 배열의 경우 각 2 차원 하위 ​​배열의 가장자리가 아니라 전체 배열의면을 검사하려고합니다.
user2357112는

아, 더 이해가 되네요. 나는 오해했다
lwileczek

1

아마도 줄임표 연산자는 당신이 찾고있는 것일 것입니다.

import numpy as np

# data
x = np.random.rand(2, 5, 5)
x[..., 0:, 0] = 0
x[..., 0, 0:] = 0
x[..., 0:, -1] = 0
x[..., -1, 0:] = 0

test = np.all(
    [
        np.all(x[..., 0:, 0] == 0),
        np.all(x[..., 0, 0:] == 0),
        np.all(x[..., 0:, -1] == 0),
        np.all(x[..., -1, 0:] == 0),
    ]
)

print(test)

이것은 모든 얼굴을 채색하지 않습니다. 예를 들어 (4, 4, 4) 큐브로 시도하십시오.
루카

나는 당신이 얼굴을 색칠하는 것이 무슨 의미인지 잘 모르겠지만 x (4, 4, 4)를
만들면 효과가 있습니다.

1

slice작업을 완료하기 위해 부울 마스킹을 사용할 수 있습니다 .

def get_borders(arr):
    s=tuple(slice(1,i-1) for i in a.shape)
    mask = np.ones(arr.shape, dtype=bool)
    mask[s] = False
    return(arr[mask])

이 함수는 먼저 배열의 "코어"를 튜플 형태로 s만든 다음 경계점 True에만 표시되는 마스크를 만듭니다 . 부울 인덱싱은 경계점을 제공합니다.

작업 예 :

a = np.arange(16).reshape((4,4))

print(a)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

borders = get_borders(a)
print(borders)
array([ 0,  1,  2,  3,  4,  7,  8, 11, 12, 13, 14, 15])

그런 다음 np.all(borders==0)원하는 정보를 제공합니다.


참고 : 이것은 1 차원 배열에서는 깨지기는하지만 가장자리를 고려합니다. 문제의 두 지점을 확인하는 것이 좋습니다.


이것은 경계가 아닌 배열의 총 요소 수에 비례하는 시간이 걸립니다. 또한 1 차원 배열은 관련없는 경우가 아닙니다.
user2357112는 Monica

1
또한, np.arange(15)15를 포함하지 않습니다.
user2357112는

나는 "부적절한"이 강력한 표현이라는 데 동의하지만, 1d 배열의 두 가지 점을 확인하는 것이 좋습니다. 15는 오타, 좋은 캐치입니다
Lukas Thaler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.