IT/언어

[python/numpy] 0 이외의 요소를 추출하는 numpy.nonzero()의 사용법

개발자 두더지 2022. 8. 20. 17:34
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있을 수 있으며 틀린 내용이 있으면 지적해주시면 감사하겠습니다.

 

 numpy.nonzero 함수는 0이 아닌 요소의 인덱스를 얻을 수 있는 심플한 함수이다. 이번 포스트에서는 numpy.nonzero의 사용법에 대해서 해설하고자한다.

 

 

numpy.nonzero


numpy.nonzero 와 numpy.ndarray.nonzero의 두 가지 타입이 있으며, 사용방법은 거의 동일하다.

numpy.nonzero의 기본 문법은 다음과 같다.

numpy.nonzero(a)

 

 

파라미터명 데이터형 개요
a  array_like 배열에 해당하는 것  인덱스를 추출하고 싶은 배열을 지정한다.

 이 함수를 통해 반환되는 것은 각 축마다 0아 이닌 요소의 인덱스를 1차원 배열이다.

 다음으로 numpy.ndarray.nonzero는 다음과 같다.

numpy.ndarray.nonzero()

 이 numpy.ndarray.nonzero를 통해서는 각 축마다 0이 아닌 요소의 인덱스를 1차원 배열을 얻을 수 있으며, 배열(ndarray)의 튜플(tuple)의 형태이다. 

 참고로, 0 이외의 값을 가진 요소의 인덱스를 추출하고 싶은 경우는 x[x.astype(bool)] 혹은 x[x=!0]  사용하면 된다. 그리고 뒤에서 설명하겠지만 nonzero()로 얻어지는 인덱스는 차원축 마다 잘려 있다. 만약 요소마다의 인덱스를 획득하고 싶은 경우는 argwhere()를 사용하자.

 

 

샘플 코드


In [1]: import numpy as np

In [2]: a = np.random.randint(0, 10, size=20)

In [3]: a # 1차원 랜덤 배열
Out[3]: array([0, 7, 5, 8, 4, 9, 0, 2, 1, 7, 9, 0, 6, 9, 2, 6, 0, 8, 3, 9])

In [4]: np.nonzero(a) # 0이 아닌 요소의 인덱스를 획득
Out[4]: (array([ 1,  2,  3,  4,  5,  7,  8,  9, 10, 12, 13, 14, 15, 17, 18, 19]),)

In [5]: a.nonzero() # 이 형태로도 사용할 수 있다.
Out[5]: (array([ 1,  2,  3,  4,  5,  7,  8,  9, 10, 12, 13, 14, 15, 17, 18, 19]),)

In [6]: a[np.nonzero(a)] # 이 작성법으로 0이 아닌 요소로만 구성된 배열을 생성할 수 있다.
Out[6]: array([7, 5, 8, 4, 9, 2, 1, 7, 9, 6, 9, 2, 6, 8, 3, 9])

In [10]: b = np.random.randint(0, 10, size= (4,5)) # 4×5의 2차원 랜덤 배열

In [11]: b
Out[11]:
array([[4, 2, 1, 7, 8],
       [5, 5, 0, 4, 7],
       [7, 6, 9, 2, 9],
       [0, 1, 2, 2, 6]])

In [12]: np.nonzero(b) # 첫 번째 배열은 "행" 방향의 인덱스, 두 번째 배열은 "열" 방향의 인덱스이다.  
Out[12]:
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3]),
 array([0, 1, 2, 3, 4, 0, 1, 3, 4, 0, 1, 2, 3, 4, 1, 2, 3, 4]))

In [13]: b.nonzero()
Out[13]:
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3]),
 array([0, 1, 2, 3, 4, 0, 1, 3, 4, 0, 1, 2, 3, 4, 1, 2, 3, 4]))

In [14]: b[b.nonzero()] # 0이 아닌 요소만을 추출했다.
Out[14]: array([4, 2, 1, 7, 8, 5, 5, 4, 7, 7, 6, 9, 2, 9, 1, 2, 2, 6])

 

 

numpy.where, numpy.argwhere과의 비교


 0이 아닌 요소를 추출할 수 있는 또 다른 방법은 두 가지 더 있다. 하나가 numpy.where이고 다른 하나가 numpy.argwhere이다. 

 numpy.where에서는 3항 연산자도 사용할 수 있다. 예를 들면 다음과 같이 쓸 수 있다.

In [2]: a = np.random.randint(0, 10, size=(100, 100))

In [3]: b = np.ones(shape=(100, 100))

In [4]: np.where(a != 0, a, b)
Out[4]:
array([[ 5.,  3.,  2., ...,  9.,  9.,  8.],
       [ 5.,  7.,  1., ...,  1.,  7.,  5.],
       [ 7.,  1.,  9., ...,  6.,  5.,  4.],
       ...,
       [ 2.,  6.,  3., ...,  9.,  6.,  9.],
       [ 4.,  2.,  4., ...,  7.,  3.,  1.],
       [ 9.,  4.,  7., ...,  3.,  6.,  5.]])

 위에서 설명했듯 요소마다의 인덱스를 획득하고 싶은 경우는 argwhere()를 사용해서 구하면 된다. 참고로 np.argwhere(a)는 np.transpose(np.nonzero(a))와 동일하다.

In [1]: import numpy as np

In [2]: a = np.random.randint(0, 10, size=(100, 100))

In [3]: np.nonzero(a)
Out[3]: (array([ 0,  0,  0, ..., 99, 99, 99]), array([ 0,  1,  2, ..., 97, 98, 99]))

In [4]: np.where(a != 0)
Out[4]: (array([ 0,  0,  0, ..., 99, 99, 99]), array([ 0,  1,  2, ..., 97, 98, 99]))

In [5]: np.argwhere(a != 0)
Out[5]:
array([[ 0,  0],
       [ 0,  1],
       [ 0,  2],
       ...,
       [99, 97],
       [99, 98],
       [99, 99]])

In [6]: np.transpose(np.nonzero(a))
Out[6]:
array([[ 0,  0],
       [ 0,  1],
       [ 0,  2],
       ...,
       [99, 97],
       [99, 98],
       [99, 99]])

참고자료

https://deepage.net/features/numpy-nonzero.html

https://www.headboost.jp/numpy-nonzero/

728x90