np.nonzero関数は、要素が0以外のインデックスを取得するシンプルな関数です。本記事では、np.nonzeroの使い方を解説します。

np.nonzero

numpy.nonzeronumpy.ndarray.nonzeroの2つのタイプがあるので両方記載しておきますが、使い方はほとんど同じです。まずは、APIドキュメントからみていきましょう。

numpy.nonzero(a)

params:

パラメータ名 概要
a array_like
配列に相当するもの
要素の抽出を行いたい配列を指定します。

returns:

非ゼロ要素のあるインデックスを各軸ごとに1次元配列にして返します。
配列(ndarray)のタプル(tuple)の形で返されます。

numpy.ndarray.nonzero()

returns:

非ゼロ要素のあるインデックスを各軸ごとに1次元配列にして返します。
配列(ndarray)のタプル(tuple)の形で返されます。

np.nonzeroは配列を引数にとります。np.ndarray.nonzeroはndarrayのメソッドとして使えます。

インデックスを返してくれるので、うまく使えば非ゼロの必要な要素だけを抽出することができます。使い方を実際のコードでみていきましょう。

In [1]: import numpy as np

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

In [3]: a # 一次元乱数配列
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) # 非ゼロ要素のインデックスを取得
Out[4]: (array([ 1,  2,  3,  4,  5,  7,  8,  9, 10, 12, 13, 14, 15, 17, 18, 19]),)

In [5]: a.nonzero() # この書式でもOK
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)] # これで非ゼロ要素抜き出した配列を生成できる。
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の二次元乱数配列

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) # 1つめの配列が行方向のインデックス、2つめの配列が列方向のインデックスになっている。  
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()] # 非ゼロ要素を抽出
Out[14]: array([4, 2, 1, 7, 8, 5, 5, 4, 7, 7, 6, 9, 2, 9, 1, 2, 2, 6])

np.where、np.argwhereとの比較

この操作はnp.where(x!=0)で全く同じことができます。np.where関数については、以下のリンクに詳しい解説があるので参照してみてください。

条件を満たす要素のインデックスを取得するNumPyのwhereの使い方 /features/numpy-where.html

np.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.]])

np.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]])

参考