note.nkmk.me

複数のNumPy配列ndarrayの要素ごとの最大値・最小値を取得

Date: 2019-09-18 / tags: Python, NumPy

複数のNumPy配列ndarrayの要素ごとの最大値・最小値を算出して新たなnumpy.ndarrayを生成するにはnumpy.maximum(), numpy.fmax(), numpy.minimum(), numpy.fmin()を使う。

numpy.maximum(), numpy.fmax(), numpy.minimum(), numpy.fmin()自体は2つのnumpy.ndarrayのみを対象とするが、reduce()を利用することで3つ以上のnumpy.ndarrayを処理することが可能。

ここでは以下の内容について説明する。

  • NumPy配列ndarrayの要素ごとの最大値を取得: maximum(), fmax()
    • 基本的な使い方
    • 形状shapeが異なる場合
  • NumPy配列ndarrayの要素ごとの最小値を取得: minimum(), fmin()
  • maximum()fmax()minimum()fmin()の違い
  • reduce()で集約
    • 複数のNumPy配列ndarrayに適用
    • 1つのNumPy配列ndarrayに適用

なお、単独のnumpy.ndarrayの全体・行ごと・列ごとの最大値・最小値はmax(), min()メソッドなどで取得できる。

import numpy as np

a = np.arange(6).reshape(2, 3)
print(a)
# [[0 1 2]
#  [3 4 5]]

print(a.max())
# 5

print(a.max(axis=0))
# [3 4 5]

print(a.max(axis=1))
# [2 5]
source: numpy_max.py
スポンサーリンク

NumPy配列ndarrayの要素ごとの最大値を取得: maximum(), fmax()

numpy.maximum(), numpy.fmax()の違いは後述の欠損値nanの扱いのみ。それ以外はどちらも全く同じ。

基本的な使い方

numpy.maximum(), numpy.fmax()の第一引数、第二引数に対象とするnumpy.ndarrayを指定する。

a = np.array([0, 1, 2])
b = np.array([2, 0, 6])

print(np.maximum(a, b))
# [2 1 6]

print(np.fmax(a, b))
# [2 1 6]

リストでもよい。

l_a = [0, 1, 2]
l_b = [2, 0, 6]

print(np.maximum(l_a, l_b))
# [2 1 6]

print(np.fmax(l_a, l_b))
# [2 1 6]

スカラー値でもよいが、組み込み関数max()でも同じ結果が得られる。

print(np.maximum(0, 2))
# 2

print(np.fmax(0, 2))
# 2

print(max(0, 2))
# 2

形状shapeが異なる場合

NumPyにおいて、形状shapeが異なるnumpy.ndarray同士の演算では、可能な場合はブロードキャストによって形状が揃えられる。

a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
#  [3 4 5]]

print(b)
# [2 0 6]

print(a_2d + b)
# [[ 2  1  8]
#  [ 5  4 11]]

numpy.maximum(), numpy.fmax()においてもブロードキャストが行われる。

print(np.maximum(a_2d, b))
# [[2 1 6]
#  [3 4 6]]

print(np.fmax(a_2d, b))
# [[2 1 6]
#  [3 4 6]]

ブロードキャストできない場合はエラーとなる。

a_mismatch = np.array([0, 1, 2, 3])

# print(np.maximum(a_mismatch, b))
# ValueError: operands could not be broadcast together with shapes (4,) (3,) 

# print(np.fmax(a_mismatch, b))
# ValueError: operands could not be broadcast together with shapes (4,) (3,) 

第一引数、第二引数のいずれかがスカラー値でもOK。各要素がスカラー値と比較される。

print(np.maximum(a_2d, 2))
# [[2 2 2]
#  [3 4 5]]

print(np.fmax(a_2d, 2))
# [[2 2 2]
#  [3 4 5]]

print(np.maximum(2, a_2d))
# [[2 2 2]
#  [3 4 5]]

print(np.fmax(2, a_2d))
# [[2 2 2]
#  [3 4 5]]

NumPy配列ndarrayの要素ごとの最小を取得: minimum(), fmin()

numpy.minimum(), numpy.fmin()numpy.maximum(), numpy.fmax()と同じ使い方。サンプルコードのみをいくつか示す。

なお、numpy.minimum(), numpy.fmin()の違いも後述の欠損値nanの扱いのみ。それ以外はどちらも全く同じ。

基本的な使い方。

a = np.array([0, 1, 2])
b = np.array([2, 0, 6])

print(np.minimum(a, b))
# [0 0 2]

print(np.fmin(a, b))
# [0 0 2]

ブロードキャストおよびスカラー値との処理。

a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
#  [3 4 5]]

print(np.minimum(a_2d, b))
# [[0 0 2]
#  [2 0 5]]

print(np.fmin(a_2d, b))
# [[0 0 2]
#  [2 0 5]]

print(np.minimum(a_2d, 2))
# [[0 1 2]
#  [2 2 2]]

print(np.fmin(a_2d, 2))
# [[0 1 2]
#  [2 2 2]]

numpy.maximum(), numpy.fmax()と同じく、引数にリストを指定することもできる。例は省略。

maximum()とfmax()、minimum()とfmin()の違い

numpy.maximum()numpy.fmax()numpy.minimum()numpy.fmin()との違いは欠損値nanの扱い。

第一引数、第二引数のnumpy.ndarrayなどにnanが含まれる場合、numpy.maximum(), numpy.minimum()では結果がnanとなり、numpy.fmax(), numpy.fmin()nanではないほうが結果となる。

print(np.maximum([np.nan, np.nan], [np.inf, 0]))
# [nan nan]

print(np.fmax([np.nan, np.nan], [np.inf, 0]))
# [inf  0.]
print(np.minimum([np.nan, np.nan], [np.inf, 0]))
# [nan nan]

print(np.fmin([np.nan, np.nan], [np.inf, 0]))
# [inf  0.]

reduce()で集約

numpy.maximum(), numpy.fmax(), numpy.minimum(), numpy.fmin()のような2つのオブジェクト(numpy.ndarrayなど)を引数とするユニバーサル関数ufuncreduce()というメソッドを持つ。

reduce()にリストなどのイテラブルを指定するとufuncがその要素に対して累積的に適用され結果が集約される。

ufunc.reduce(x)は基本的には... ufunc(ufunc(ufunc(x[0], x[1]), x[2]), x[3]) ...に等しい。

複数のNumPy配列ndarrayに適用

numpy.maximum()を例とすると以下のようになる。

a = np.array([0, 1, 2])
b = np.array([3, 0, 6])
c = np.array([1, 2, 3])

print(np.maximum.reduce([a, b, c]))
# [3 2 6]

以下のような処理と同じ。

print(np.maximum(np.maximum(a, b), c))
# [3 2 6]

numpy.fmax(), numpy.minimum(), numpy.fmin()でも同様。

print(np.fmax.reduce([a, b, c]))
# [3 2 6]

print(np.minimum.reduce([a, b, c]))
# [0 0 2]

print(np.fmin.reduce([a, b, c]))
# [0 0 2]

reduce()の引数にはリストなどのイテラブルを指定する必要がある。リストではなくタプルなどでもいいが、各オブジェクトをそのままカンマ区切りで指定するとエラー。

print(np.maximum.reduce((a, b, c)))
# [3 2 6]

# print(np.maximum.reduce(a, b, c))
# TypeError: data type not understood

なお、reduce()を使うと関数が繰り返し適用されると書いたが、各オブジェクトの形状が異なる場合、NumPy1.16.4時点ではエラーになった。元の関数(ここではnumpy.maximum())を繰り返すと問題ない。

a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
#  [3 4 5]]

# print(np.maximum.reduce([a_2d, b, c]))
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

print(np.maximum(np.maximum(a_2d, b), c))
# [[3 2 6]
#  [3 4 6]]

numpy.ndarrayとスカラー値が混在する場合も同じ。

# print(np.maximum.reduce([4, b, c]))
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

print(np.maximum(np.maximum(4, b), c))
# [4 4 6]

ソースコードを追っていないのでバグなのかこういう仕様なのかは未確認だが要注意。

1つのNumPy配列ndarrayに適用

reduce()の引数に一次元のnumpy.ndarrayを指定すると、要素に対して順に関数(ここではnumpy.maximum())が適用される。

この場合、numpy.ndarraymax()メソッドや組み込み関数max()で同様の結果が得られるので、numpy.maximum()reduce()を使う必要はない。

print(a)
# [0 1 2]

print(np.maximum.reduce(a))
# 2

print(a.max())
# 2

print(max(a))
# 2

多次元のnumpy.ndarrayも同様。

ufunc.reduce(x)... ufunc(ufunc(ufunc(x[0], x[1]), x[2]), x[3]) ...に等しいという考え方の通りに処理される。

これもmax()メソッドで引数axisを指定すれば同様の結果が得られる。あえてnumpy.maximum()reduce()を使う必要はない。

a_2d = np.array([[0, 1, 2], [3, 0, 6], [1, 2, 3]])
print(a_2d)
# [[0 1 2]
#  [3 0 6]
#  [1 2 3]]

print(np.maximum.reduce(a_2d))
# [3 2 6]

print(np.maximum(np.maximum(a_2d[0], a_2d[1]), a_2d[2]))
# [3 2 6]

print(a_2d.max(axis=0))
# [3 2 6]
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事