NumPyで最大値を取得するamax(), nanmax()関数とmax()メソッドの使い方

NumPyには配列の最大値を取得するための関数であるnp.amax()と、メソッドであるndarray.max()が用意されています。

np.amax()ndarray.max() は、前者が関数で後者がメソッドという点を除いて全く同じです。関数の場合は np.amax(a) というように引数に対象となる配列を渡しますが、メソッドの場合は a.max() というように対象となる配列の後ろに繋げて書きます。

これらに加えて、np.nanmax()という関数もあります。これも、np.amax()と同じですが、欠損値nanに対する扱いが異なります。np.amax()は対象となる配列に欠損値nanが含まれる場合、nanを返します。一方で、np.nanmax()は欠損値nanを無視して最小値を返します。

まとめると次のようになります。

  • np.amax: 配列内の最大値を取得する関数(nan優先)
  • np.nanmax: 配列内の最大値を取得する関数(nan無視)
  • ndarray.max: 配列内の最大値を取得するメソッド

このページでは、これらの関数について解説します。

NumPy配列の最大値の操作まとめ
NumPy配列の最大値を操作する全方法については、『NumPy配列の最大値やそのインデックスを取得する関数とメソッドまとめ』ですべてまとめています。ぜひ一度ご確認ください。

目次

1. 書式

まずは書式を確認しておきましょう。np.amax()np.nanmax()は全く同じなので、ここではnp.amax()のみ記しておきます。

なお、これから見ていく通り、この関数には多くのオプション引数があります。ただし、実際によく使うのは axis ぐらいです。その次に使う可能性があるのは、keepdims, initial です。そのため、この3つを抑えておくようにすると良いでしょう。

numpy.amax関数

書き方:

np.amax(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)

パラメーター:

引数 解説
a   array_like   最大値を求める対象である配列を渡します。
axis*   None or int or tuple of ints    a が多次元配列の場合、どの次元軸の最大値を求めるかを指定します。
out*  ndarray  ここで指定した配列を、関数の戻り値で上書きします。双方の配列のshapeが一致している必要があります。
keepdims*    bool これをTrueに指定すると、元の配列の次元数を維持します。ブロードキャストに便利です。
initial*  scalar ここで指定した値より大きな値がない場合は、この値を返します。
where* array_like of bool       要素がブール値の配列を渡すと、Trueに該当する要素のみを対象としてその中の最大値を返します。
* はオプション引数であることを示します。

戻り値: 

最大値を要素とする配列またはスカラー
配列aの最大値を求めます。axis=Noneの時は、スカラー(要素が1つの配列)が生成されます。axisを指定した時は、生成される配列の次元数は元の配列の次元数-1になります。

一緒に確認したい関数:

  • amin: 配列の指定の軸方向の要素のうち最小値を取得。欠損値NaN優先。
  • nanmax: 配列の指定の軸方向の要素のうち最大値を取得。欠損値NaNは無視。当ページ内で解説。
  • maximum: 2つの配列の各要素のうち値が大きい方を取得。欠損値NaN優先。
  • fmax: 同上。欠損値NaNは無視。上と同じページで解説。
  • argmax: 最大値のインダイスを取得。
  • nanmin, minimum, fmin
ndarray.maxメソッド

書き方:

ndarray.max(axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)

2. サンプルコード

それでは実際にサンプルコードを見て確認していきましょう。

なお、上述の通りnp.amax()np.nanmax()は欠損値の扱いを除いて全く同じです。ndarray.max()np.amax()と同じですが、メソッドであるため、a.max()というように対象となる配列を前に書きます。

すべてを同じように解説すると煩雑になるため、ここからはnp.amax()をメインに解説を進めていきます。

1次元配列の最大値

対象となる配列a が1次元配列の場合、np.amax()は、その中の最大値を返します。

以下の配列を例に見てみましょう。

In [1]:
import numpy as np
rng = np.random.default_rng()
a = rng.integers(-10, 11, (5, ))
a
Out[1]:
array([-2, -4,  6, -3,  2])

この配列a をnp.amax()に渡すと、最大値を返します。

In [2]:
# 最大値を返す
np.amax(a)
Out[2]:
6

ndarray.max()メソッドの場合は次のように書きます。

In [3]:
# メソッドの場合
a.max()
Out[3]:
6

配列の中に欠損値nanがある場合は、np.amax()ndarray.max()はnanを返します。

In [1]:
import numpy as np
a = np.array([  7,  1, -10,  -3,  5, np.nan])
a
Out[1]:
array([  7.,   1., -10.,  -3.,   5.,  nan])
In [2]:
# 欠損値nanがある場合はnanを返す。
np.amax(a)
Out[2]:
nan
In [3]:
# メソッドも同様にnanを返す。  
a.max()
Out[3]:
nan

ただし、np.nanmax()は欠損値nanを無視して最大値を返します。これらの違いを覚えておいて使い分けられるようにしましょう。

In [4]:
#  np.nanmax()関数はnanを無視して最大値を返す。
np.nanmax(a)
Out[4]:
7.0

多次元配列の最大値を取得

多次元配列の場合も、デフォルトでは、全要素の中から最大値を返します。以下の配列を例に見ていきましょう。

In [1]:
import numpy as np
rng = np.random.default_rng()
a = rng.integers(-10, 11, (3, 5))
a
Out[1]:
array([[ 2,  0, -3, -2,  4],
       [10, -3,  5, -5,  6],
       [-1,  4,  0,  3, -6]])

以下のように、デフォルトでは次元数に関わらず、全要素の中の最大値を返します。

In [2]:
# デフォルトでは全要素のうち最大値を返す。
np.amax(a)
Out[2]:
10
In [3]:
# メソッドも同じ
a.max()
Out[3]:
10

次元軸を指定して最大値を取得

オプション引数 axis で、最大値を求める次元軸を指定することができます。1次元軸を指定した場合は、各行の中の最大値を返します。

In [4]:
# 1次元軸(横軸)を指定
np.amax(a, axis=-1)
Out[4]:
array([ 4, 10,  4])

2次元軸を指定した場合は、各列の中の最大値を返します。

In [5]:
# 2次元軸(縦軸)を指定
np.amax(a, axis=0)
Out[5]:
array([10,  4,  5,  3,  6])

ndarray.max()メソッドでも同じです。

In [6]:
# メソッドも同じ
a.max(axis=-1)
Out[6]:
array([ 4, 10,  4])
In [7]:
a.max(axis=0)
Out[7]:
array([10,  4,  5,  3,  6])

重要: np.maximum()を使うべきケース

多次元配列で最初の軸の要素数が2の場合、つまり2次元配列なら shape(2, n)、3次元配列ならshape(2, n, k)の場合、で最初の軸(axis=0)の最大値を取得する場合は、np.amax()よりもnp.maximum()の方が高速です。

以下の一連のコードをご覧ください。

In [1]:
# 最初の軸(axis=0)の要素数が2の配列を作成
import numpy as np
rng = np.random.default_rng()
a = rng.integers(-10, 11, (2, 3, 4))
a
Out[1]:
array([[[  2,  -8, -10,  -4],
        [ -5,  -5,   4,   9],
        [ 10,  -1,  10,   1]],

       [[ -2,  -9,   7,  -7],
        [ -9,   4,   4,   7],
        [  3,   2,  -3,  -6]]])
In [2]:
# この場合はnp.amaxよりもnp.maximumの方が遥かに高速
np.amax(a, axis=0)
Out[2]:
array([[ 2, -8,  7, -4],
       [-5,  4,  4,  9],
       [10,  2, 10,  1]])
In [3]:
np.maximum(a[0], a[1])
Out[3]:
array([[ 2, -8,  7, -4],
       [-5,  4,  4,  9],
       [10,  2, 10,  1]])

この場合、出力結果は同じですが np.maximum()の方が遥かに高速です。実際に処理時間を計測してみましょう。

In [4]:
%%timeit
np.amax(a, axis=0)
4.9 µs ± 208 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [5]:
%%timeit
np.maximum(a[0], a[1])
933 ns ± 33 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

このように、両者の間には5倍近い速度差があります。この点は、ぜひ覚えておきましょう。

元の配列の次元数を維持して最小値を取得

オプション引数で keepdims=True にすると、元の配列の次元数を維持したまま最大値を出力してくれます。つまり、元の配列とブロードキャスト可能な形状になります。

以下の一連のコードでご確認ください。

In [1]:
import numpy as np
rng = np.random.default_rng()
a = rng.integers(-10, 11, (3, 5))
a
Out[1]:
array([[  7, -10,   0, -10,   9],
       [-10,   2,   6,  -5,  -8],
       [ -6,   6,   1,   5,   8]])
In [2]:
# 次元数を維持
np.amax(a, axis=-1, keepdims=True)
Out[2]:
array([[9],
       [6],
       [8]])
In [3]:
np.amax(a, axis=0, keepdims=True)
Out[3]:
array([[7, 6, 6, 5, 9]])
In [4]:
# メソッドでも同じ
a.max(axis=-1, keepdims=True)
Out[4]:
array([[9],
       [6],
       [8]])
In [5]:
a.max(axis=0, keepdims=True)
Out[5]:
array([[7, 6, 6, 5, 9]])

任意の最大値を指定

オプション引数のinitialを使うと、指定した値よりも大きな値が配列内にない場合は、この値を返すようになります。

以下の一連のコードでご確認ください。

In [1]:
import numpy as np
rng = np.random.default_rng()
a = rng.integers(-10, 1, (5, ))
a
Out[1]:
array([ -5,  -8,  -4,  -9, -10])
In [2]:
np.amax(a, initial=10)
Out[2]:
10
In [3]:
# メソッドでも同じ
a.max(initial=10)
Out[3]:
10

なお、NumPyのamax()のオプション引数initialと、Python組み込み関数のmax()のオプション引数dfaultで混同されやすい点があります。

Pythonの組み込み関数max()のオプション引数defaultは、関数に渡した配列の要素が空の時に返す値です。一方で、np.amax()のオプション引数initialは、配列の中に指定した値より大きな値がない場合に、指定の値を返します。

この点を混同のないように覚えておきましょう。

3. まとめ

以上が、np.amax()ndarray.max()np.nanmax()それぞれの使い方です。

冒頭でも述べましたが、それぞれの使い分け方は以下の通りです。

  • np.amax: 配列内の最大値を取得する関数(nan優先)
  • np.nanmax: 配列内の最大値を取得する関数(nan無視)
  • ndarray.max: 配列内の最大値を取得するメソッド

ぜひ参考にして頂ければ幸いです。



よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

目次
閉じる