[NumPy超入門]多次元配列から最大値/最小値を求めてみようPythonデータ処理入門

NumPyには最大値や最小値を求める関数/メソッドがとてもたくさん用意されています。それらの幾つかと最大値や最小値を求める際に注意が必要なNaN値の扱いについて見ていきます。

» 2023年08月18日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「Pythonデータ処理入門」のインデックス

連載目次

連載概要

 本連載はPythonについての知識を既にある程度は身に付けている方を対象として、Pythonでデータ処理を行う上で必須ともいえるNumPyやpandas、Matplotlibなどの各種ライブラリの基本的な使い方を学んでいくものです。そして、それらの使い方をある程度覚えた上で、それらを活用してデータ処理を行うための第一歩を踏み出すことを目的としています。


最大値の取得

 NumPyの多次元配列(numpy.ndarrayオブジェクト)に格納されている要素から最大値を抽出するのに使える関数やメソッドには幾つかの種類があります。

関数/メソッド 説明 NaNがあった場合
numpy.amax関数 引数に指定した配列の要素から最大値を返す NaNを返す
numpy.nanmax関数 引数に指定した配列の要素から最大値を返す NaNを無視する
numpy.ndarray.maxメソッド 呼び出しに使用した配列の要素から最大値を返す NaNを返す
numpy.maximum関数 引数に指定した2つの配列を対応する要素ごとに比較して大きい方の値を取り出し、それらを要素とする新しい配列を作成して戻り値とする NaNを返す
numpy.fmax関数 引数に指定した2つの配列を対応する要素ごとに比較して大きい方の値を取り出し、それらを要素とする新しい配列を作成して戻り値とする NaNを無視する
numpy.argmax関数 最大値を含んでいる要素のインデックスを返す NaNが含まれているインデックス位置を返す
numpy.ndarray.argmaxメソッド 最大値を含んでいる要素のインデックスを返す NaNが含まれているインデックス位置を返す
最大値を取得する関数/メソッド

 以下ではこれらの関数について簡単に見ていきましょう。

numpy.amax関数

 numpy.amax関数の構文を以下に示します。

numpy.amax(a, axis=None, out=None, keepdims=<no value>)

numpy.amax関数の構文(抜粋)

 パラメーターの意味は以下の通りです。

  • a:最大値を調べたいndarrayオブジェクトを指定
  • axis:最大値を求めたい軸(0始まり)
  • out:結果を格納する配列。numpy.amax関数が算出する結果と同じ形状でなければならない
  • keepdims:Trueを指定すると戻り値の次元数が元のndarrayオブジェクトと同じになる

 numpy.amax関数に配列だけを渡したときには、その配列の全要素の中で最大の値が返されます。以下はその例です。

a = np.arange(12).reshape((3, 4))
print(a)
# 出力結果:
#[[ 0  1  2  3]
# [ 4  5  6  7]
# [ 8  9 10 11]]

m = np.amax(a)
print(m)  # 11

最大値の取得

 この例では配列のみを渡しているので、 その中の最大値が返されます(このときには、元の配列を1次元化したものが渡されます)。

 axisに最大値を求める際にどの軸に沿って進むかを指定することも可能です。以下は行方向に最大値を検索する例です。

m = np.amax(a, axis=0# 行方向
print(m)  # [ 8  9 10 11]

行に沿って最大値を探していく

 この例では「axis=0」と指定しているので、行インデックスが小さい方から大きい方へと進みながら最大値が検索されて、見つかった最大値(11)が含まれる行が戻り値になっています。

 一方、「axis=1」を指定した例が以下です。

m = np.amax(a, axis=1# 列方向
print(m)  # [ 3  7 11]

列に沿って最大値を探していく

 この例では各行を列インデックスが小さい方から大きい方へと進みながら最大値を検索して、最大値(11)が含まれる列が戻り値になっています。

 実際には以下のように行と列を(さらに次元数が多ければ、それらの軸の方向も)タプル形式で渡すことも可能です。

m = np.amax(a, axis=(0, 1))  # 行方向/列方向
print(m)  # 11

行と列を指定

 この場合には、最大値がそのまま取り出されます。

 出力を新規の配列に保存しておきたいときにはoutに、numpy.amax関数の戻り値と同じ形状となる配列を渡します。

o = np.empty_like(a[0])
m = np.amax(a, axis=0, out=o)
print(m)  # [ 8  9 10 11]
print(o)  # [ 8  9 10 11]

o = np.empty_like(a[:, 0])
m = np.amax(a, axis=1, out=o)
print(m)  # [ 3  7 11]
print(o)  # [ 3  7 11]

出力を新しい配列に保存

 最初の例ではnumpy.amax関数に「axis=0」を指定しています。そのため、戻り値は4要素の1次元配列です。よって、numpy.empty_like関数を使って、 そうした配列を作成している点に注意してください。

 ここで使用しているnumpy.empty_like関数は、引数と指定した配列と同じ形状で、同じデータ型を要素の型とする配列を新規に作成するものです。

 次の例では「axis=1」と指定しているので、戻り値は3要素の1次元配列になります。これに合わせて、列方向の形状を指定するためにempty_like関数に「a[:, 0]」を渡しています。

 最後のkeepdimsは戻り値の次元数を、元の配列と同じようにするかどうかの指定です。以下に例を示します。

m = np.amax(a, keepdims=True)
print(m)  # [[11]]

m = np.amax(a, axis=0, keepdims=True)
print(m)  # [[ 8  9 10 11]]

keepdims=Trueを指定する例

 ところでNumPyで扱うデータには、データがあるはずのところなのにデータがない(欠損している)といった場合もあります。NumPyではこれらはNaN(Not a Number)値として扱うことが一般的です。NaN値を表すのに、NumPyではnp.nanオブジェクトが使われます。

 どうしてそんな話を突然したかというと、numpy.amax関数は配列中にNaN値があった場合に、それらを最大値として取り出すからです。

a = np.array([np.nan, 0, 1])
m = np.amax(a)
print(m)  # nan

numpy.amax関数では配列中に存在するNaN値を最大値として返送する

 このやり方だと問題があるときには、次に紹介するnumpy.nanmax関数を使うとよいでしょう。

numpy.nanmax関数

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。