[python] numpy 배열에 0 만 포함되어 있는지 테스트

다음과 같이 0으로 numpy 배열을 초기화합니다.

np.zeros((N,N+1))

그러나 주어진 n * n numpy 배열 행렬의 모든 요소가 0인지 어떻게 확인합니까?
이 메서드는 모든 값이 실제로 0 인 경우 True를 반환하면됩니다.



답변

numpy.count_nonzero를 확인하십시오 .

>>> np.count_nonzero(np.eye(4))
4
>>> np.count_nonzero([[0,1,7,0,0],[3,0,0,2,19]])
5


답변

여기에 게시 된 다른 답변은 작동하지만 가장 명확하고 효율적인 기능은 numpy.any()다음과 같습니다.

>>> all_zeros = not np.any(a)

또는

>>> all_zeros = not a.any()
  • numpy.all(a==0)더 적은 RAM을 사용하기 때문에 선호 됩니다. ( a==0용어에 의해 생성 된 임시 어레이가 필요하지 않습니다 .)
  • 또한 numpy.count_nonzero(a)0이 아닌 첫 번째 요소가 발견되면 즉시 반환 될 수 있기 때문에 더 빠릅니다 .
    • 편집 : @Rachel이 주석에서 지적했듯이 np.any()더 이상 “단락”논리를 사용하지 않으므로 소형 어레이의 경우 속도 이점이 나타나지 않습니다.


답변

배열 a가있는 경우 여기에서 np.all을 사용합니다.

>>> np.all(a==0)


답변

또 다른 대답이 말했듯이, 그것이 0배열에서 가능한 유일한 거짓 요소 라는 것을 알고 있다면 진실 / 거짓 평가를 활용할 수 있습니다 . 배열의 모든 요소는 진실한 요소가 없으면 거짓입니다. *

>>> a = np.zeros(10)
>>> not np.any(a)
True

그러나 대답은 any부분적으로 단락으로 인해 다른 옵션보다 빠르다고 주장했습니다 . 2018 년부터 Numpy allany 단락하지 마십시오 .

이런 종류의 작업을 자주 수행하면 다음을 사용하여 단락 버전을 만드는 것이 매우 쉽습니다 numba.

import numba as nb

# short-circuiting replacement for np.any()
@nb.jit(nopython=True)
def sc_any(array):
    for x in array.flat:
        if x:
            return True
    return False

# short-circuiting replacement for np.all()
@nb.jit(nopython=True)
def sc_all(array):
    for x in array.flat:
        if not x:
            return False
    return True

단락되지 않은 경우에도 Numpy 버전보다 빠른 경향이 있습니다. count_nonzero가장 느립니다.

성능을 확인하기위한 몇 가지 입력 :

import numpy as np

n = 10**8
middle = n//2
all_0 = np.zeros(n, dtype=int)
all_1 = np.ones(n, dtype=int)
mid_0 = np.ones(n, dtype=int)
mid_1 = np.zeros(n, dtype=int)
np.put(mid_0, middle, 0)
np.put(mid_1, middle, 1)
# mid_0 = [1 1 1 ... 1 0 1 ... 1 1 1]
# mid_1 = [0 0 0 ... 0 1 0 ... 0 0 0]

검사:

## count_nonzero
%timeit np.count_nonzero(all_0) 
# 220 ms ± 8.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.count_nonzero(all_1)
# 150 ms ± 4.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

### all
# np.all
%timeit np.all(all_1)
%timeit np.all(mid_0)
%timeit np.all(all_0)
# 56.8 ms ± 3.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 57.4 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 55.9 ms ± 2.13 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# sc_all
%timeit sc_all(all_1)
%timeit sc_all(mid_0)
%timeit sc_all(all_0)
# 44.4 ms ± 2.49 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 22.7 ms ± 599 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 288 ns ± 6.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

### any
# np.any
%timeit np.any(all_0)
%timeit np.any(mid_1)
%timeit np.any(all_1)
# 60.7 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 60 ms ± 287 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 57.7 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# sc_any
%timeit sc_any(all_0)
%timeit sc_any(mid_1)
%timeit sc_any(all_1)
# 41.7 ms ± 1.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 22.4 ms ± 1.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 287 ns ± 12.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

* 유용 all하고 any동등 함 :

np.all(a) == np.logical_not(np.any(np.logical_not(a)))
np.any(a) == np.logical_not(np.all(np.logical_not(a)))
not np.all(a) == np.any(np.logical_not(a))
not np.any(a) == np.all(np.logical_not(a))


답변

다른 numpy 함수에 대한 경고를 피하기 위해 모든 0을 테스트하는 경우 try로 줄을 래핑합니다. except 블록은 관심있는 작업 전에 0에 대한 테스트를 수행해야하는 시간을 줄여줍니다.

try: # removes output noise for empty slice 
    mean = np.mean(array)
except:
    mean = 0


답변