NumPyのargmin関数は、配列内の最小値のインデックスを返す関数です。全く同じ機能のものに、ndarray.argmin()メソッドも用意されています。
通常、NumPyの配列から最小値を取得するにはnp.amin()を使います。しかし、np.argmin()で取得できるインダイスを使うと、より複雑な操作を行うことが可能です。NumPyの配列には、Python標準のリストやタプルと比べて、豊富なスライスのテクニックが用意されているからです。そのため、np.argmin()を使いこなすには、インダイスの配列を使ったスライスのテクニックを身につけておく必要があります。
それでは、このページでは、np.argmin()の使い方についてサンプルコードを見ながら確認していきます。
インデックスの配列を使いこなすための全スキル
NumPyの配列は、様々なスライスのテクニックが用意されています。その中でも特に重要なのは、インデックスの配列によるスライスのテクニックでしょう。これらに関して詳しくは、『NumPyの配列のスライスの必須テクニックまとめ』ですべてまとめています。インデックス配列を使いこなすためにも、ぜひご確認頂ければと思います。
NumPy配列の最小値の操作まとめ
NumPy配列の最小値を操作する全方法については、『NumPy配列の最小値やそのインデックスを取得する関数・メソッドまとめ』ですべてまとめています。ぜひ一度ご確認ください。
1. 書式
まずは書き方と引数を確認しましょう。
書き方:
numpy.argmin(a, axis=None, out=None)
パラメーター:
引数 | 型 | 解説 |
a | array_like | 配列を渡します。 |
axis* | int | どの軸を基準に最小値を求めるかを指定します。デフォルト(None)では配列全体の要素の中の最小値を1つだけ取得します。 |
out* | array | ここで指定した配列を、関数の戻り値で上書きします。指定する配列のshapeとdtypeが適切である必要があります。 |
* はオプション引数であることを示します。 |
戻り値:
ndarray: 最小値のインダイス(インデックスの複数形)を要素とした配列を戻します。生成される配列のshapeは、元の配列のshapeから、指定したaxisを削除したものになります。 |
一緒に確認したい関数:
書き方:
ndarray.argmin(axis=None, out=None)
2. サンプルコード
実際のコードを見ながら使い方を確認していきましょう。
なお、np.argmin関数とndarray.argminメソッドは機能は全く同じなので、ここではnp.argmin関数で解説していきます。
1次元配列の場合
まずは、以下の1次元配列を例に見てみましょう。
import numpy as np
rng = np.random.default_rng()
arr = rng.integers(0, 10, (10, ))
arr
この配列を関数に渡すと、最小値のインデックスを返します。
# 最小値のインデックスを取得
np.argmin(arr)
スライスすると値を参照することができます。スライスについては『NumPyの配列のスライスの必須テクニックまとめ』で解説しています。
# スライスして値を取得
arr[8]
確かに、最小値である0を参照しています。なお、この例のように最小値が複数ある場合は最初のインデックスを返します。
多次元配列の場合
多次元配列を渡した時は、その多次元配列を1次元配列化(flatten)した時のインデックスを返します。
以下のコードでご確認ください。
import numpy as np
rng = np.random.default_rng()
arr = rng.integers(0, 10, (2, 3))
arr
# 最小値のインデックスを取得
np.argmin(arr)
この場合、値を参照するには、元の多次元配列をndarray.flatten
メソッドで1次元配列化してからスライスします。
# スライスして値を取得
arr.flatten()[4]
または、以下のように、インダイスを任意のshapeに対応する形に変換してくれるunravel_index()を使う方法もあります。
# 元の2次元配列arr のshapeに対応するインダイスを取得
ind = np.unravel_index(np.argmin(arr, axis=None), arr.shape)
ind
arr[ind]
unravel_index()は、第一引数にインダイスの配列を渡し、第二引数で変換したいshapeを指定します。インダイスを扱う上で非常に便利なので、一緒に覚えておくと良いでしょう。
次元軸を指定
オプション引数axis=
を使うと、要素を検索する次元軸を指定することができます。以下の2次元配列を使って確認しましょう。
import numpy as np
rng = np.random.default_rng()
arr = rng.integers(0, 10, (2, 3))
arr
axis=0
は最初の軸を指定することと同じです。2次元配列では、最初の軸は2次元軸(縦軸)に該当します。
以下で確認しましょう。
# 2次元軸(縦軸)の最小値のインデックスを取得
ind = np.argmin(arr, axis=0)
ind
このインダイスから各列の最小値を一括取得するには、以下のようにtake_along_axis()を使います。
# 2次元軸(縦軸)ごとの最小値を一括取得
ind_array = np.expand_dims(ind, axis=0) #インデックス配列の次元数をaに合わせる
np.take_along_axis(arr, ind_array, axis=0)
expand_dimsは配列の次元数を増やす関数です。これによって、元の配列a の次元数とインダイス配列ind の次元数を揃えてブロードキャスト可能にしています。np.take_arlong_axisは多次元配列から指定のインデックス番号の要素を一括して取得する関数です。こちらの関数では、元の配列a とインダイス配列の次元数が揃っている必要があります。
axis=1
を指定した時は、1次元軸(横軸)の要素から最小値のインデックスを取得します。
# 1次元軸(横軸)の最小値のインデックスを取得
ind = np.argmin(arr, axis=-1)
ind
1次元軸ごとの最小値を一括取得するには、同じくtake_along_axis()を使います。
# 1次元軸(横軸)ごとの最小値を一括取得
ind_array = np.expand_dims(ind, axis=-1) #インデックス配列の次元数をaに合わせる
np.take_along_axis(arr, ind_array, axis=-1)
3次元配列以上になっても考え方は同じです。
戻り値で既存の配列を上書き
使うことはほぼありませんが、オプション引数 out= で、既存の配列を戻り値の配列で上書きすることができます。この時、お互いの配列とデータ型の形状が一致している必要があります。
以下のコードでご確認ください。
# 配列を作成
import numpy as np
rng = np.random.default_rng()
arr = rng.integers(5, size=(2, 5))
arr
# 上書きする配列を作成
x = np.zeros(5, dtype=int)
x
# np.argminの戻り値でxを上書き
np.argmax(arr, axis=0, out=x)
x
3. まとめ
以上が、np.argmin関数の使い方です。
ページ中で解説してた np.expand_dims や np.take_along_axis、np.unravel_index の書き方もしっかり頭に入れておきましょう。
なお、ndarray.argminメソッドも使い方はまったく同じです。念のためサンプルコードを貼っておきます。
import numpy as np
# 配列を生成
rng = np.random.default_rng()
arr = rng.integers(0, 10, (2, 3))
print('arr:\n', arr, '\n')
# メソッドなので配列を前に書く
print('arr.argmin()\n', arr.argmin(), '\n')
# axisの指定
print('arr.argmin(axis=0)\n', arr.argmin(axis=0), '\n')
# outの指定
a_out = np.zeros(2, dtype=int)
arr.argmin(axis=1, out=a_out)
print('a_out:\n', a_out)
コメント