この記事では、Python でリストなどから最大値や最小値を抜き出すいくつかの方法について解説します。
【Python】要素の最大値(Maximum value)
コンピューターで最大値を求めるアルゴリズムはそれほど難しくはありません。numbers という名前のリストにいくつかの数値が格納されているとします。最初に numbers[0] を最大値と仮定して、その値を変数(ここでは max_val とします)に格納します。次に max_val と numbers[1] を比較して、max_val のほうが大きければ(あるいは等しければ)そのままに、numbers[1] のほうが大きければ max_val の値を numbers[1] の値で置き換えます。これを順次繰り返していけば、max_val にはリストの最大値が格納されているはずです。以下がサンプルコードです。
# 最大値を返す関数のサンプル def max_sample(numbers): max_val = numbers[0] for x in numbers: if x > max_val: max_val = x return max_val my_number = [3, 0, 11, 7, 5] print(max_sample(my_number)) # 11
以下に、イテラブルを受け取って要素の最大値(max)を返す Python 関数の一覧を掲載します。
max()
Python の組み込み関数 max() は 2 個以上の引数を受け取って、最大値を選んで返します。
# PYTHON_MAX # In[1] # 10,20,30の中から最大値を取得 val = max(10, 20, 30) print(val) # 30
max() にイテラブル・オブジェクトを渡すと、オブジェクトの 最大要素を返します。
# In[2] num = [65, 42, 68, 83, 55] # numの最大要素を取得 val = max(num) print(val) # 83
タプルを要素にもつリストなどを引数に渡す場合、key に関数を渡して、特定のインデックスの要素同士を比較して最大値を得ることもできます。以下のコードでは、インデックス番号 1 の要素を取り出す lambda式(無名関数)を key に渡しています。
# In[3] num = [(5, 3), (1, 4), (4, 9)] # 2番目の要素が最大となるタプルを取得 val = max(num, key=lambda x:x[1]) print(val) # (4, 9)
文字列 (テキストシーケンス) もイテラブルなので、max() の第 1 引数に渡せます。たとえば、”abcde” という文字列の最大値は “e” となります。
# In[4] val = max("abcde") print(val) # e
文字コードによって、アルファベットは大文字の A から始まって Z まで、そのあと小文字の a~z が続くというように順序づけられているからです。同様に平仮名にも順序があります。文字列 “あいうえお” の最大値は “お” となります。
# In[5] val = max("あいうえお") print(val) # お
numpy.max()
numpy.max() に配列を渡すと配列要素の最大値を返します。オプション引数 axis を指定した場合、指定した軸ごとに最大要素を取り出して一次元配列を生成します。
# NUMPY_MAX # In[1] # NumPyをインポート import numpy as np # 要素の最大値を取得 x_max = np.max(x) # 各列の最大要素を取り出して1次元配列を生成 x_max_0 = np.max(x, axis=0) # 各行の最大要素を取り出して1次元配列を生成 x_max_1 = np.max(x, axis=1) print(x_max) print(x_max_0) print(x_max_1) # 79 # [52 79 62] # [52 79]
keepdims に True を渡すと、もとの配列の次元を保持します。
# In[2] # x = [[52, 35, 41], # [18, 79, 62]] # 各列の最大要素を取り出して1次元配列を生成(次元を保持) x_max_0k = np.max(x, axis = 0, keepdims = True) print(x_max_0k) # [[52 79 62]]
nan は常に最大値として扱われます。
# In[3] x = np.array([61, 12, 80, np.nan, 74]) x_max = np.max(x) print(x_max) # nan
nan を最大値として扱いたくない場合は以下で解説する numpy.nanmax を使ってください。
numpy.nanmax()
numpy.nanmax() は nan を無視して要素の中から最大値を選んで float で返します。
# NUMPY_NANMAX # In[1] x = np.array([61, 12, 80, np.nan, 74]) x_nanmax = np.nanmax(x) print(x_nanmax) # 80.0
numpy.argmax()
numpy.argmax() は配列要素の最大値のインデックスを返します。
# NUMPY_ARGMAX # In[1] x = np.array([81, 25, 41, 96, 58]) # 最大要素のインデックスを取得 x_max = np.argmax(x) print(x_max) # 3
axis を指定すると、軸ごとの最大値のインデックスを格納した新しい配列を生成します。
# In[2] x = np.array([[28, 63, 14], [77, 22, 40]]) # 列ごとの最大値のインデックスで配列を生成 x_max_0 = np.argmax(x, axis=0) # 行ごとの最大値のインデックスで配列を生成 x_max_1 = np.argmax(x, axis=1) print(x_max_0) print(x_max_1) # [1 0 1] # [1 0]
numpy.maximum()
numpy.maximum(x1, x2) は配列 x1 と配列 x2 の各要素を比較し、小さくないほうの値(最大値)を要素にもつ新しい配列を生成します。x1 と x2 は同じ形状、もしくはブロードキャスト可能な形状をしていなければなりません。
# NUMPY_MAXIMUM # In[1] x1 = np.array([15, 60, 47, 8, 20]) x2 = np.array([49, 60, 25, 21, 33]) # x1とx2の各要素を比較して小さくないほうを要素にもつ配列を生成 y = np.maximum(x1, x2) print(y) # [49 60 47 21 33]
x1 が 1 次元配列、x2 が数値(スカラー)である場合、x2 は同じ数値をもつ 1 次元配列にブロードキャストされたうえで、各要素が比較されて新しい配列が生成されます。すなわち、x1 の各要素と数値 x2 が比較され、小さくないほうが新しい配列の要素となります。
# In[2] x1 = np.array([15, 60, 47, 8, 20]) # x1の各要素と30を比較して小さくないほうを要素にもつ配列を生成 # (30は1次元配列[30, 30, 30, 30, 30]にブロードキャストされる) y = np.maximum(x1, 30) print(y) # [30 60 47 30 30]
【Python】要素の最小値(Minimum value)
イテラブルを受け取って、要素の最小値を返す関数の一覧です。
min()
Python の組み込み関数 min() は 2 個以上の引数を受け取って、最小値を選んで返します。
# PYTHON_MIN # In[1] # 10,20,30の中から最小数を取得 val = min(10, 20, 30) print(val) # 10
min() にイテラブル・オブジェクトを渡すと、オブジェクトの 最小値 を返します。
# In[2] num = [33, 94, 61, 70, 65] # numの最小要素を取得 val = min(num) print(val) # 33
タプルを要素にもつリストなどを引数に渡すとき、key に適切な関数を渡して、特定のインデックスの要素同士を比較することによって、最小値を取得することも可能です。以下のコードでは、インデックス番号 2 の要素を取り出す lambda 関数(無名関数)を key に渡しています。
# # In[3] num = [(5, 7, 2), (0, 3, 4), (9, 2, 1)] # 3番目の要素が最小となるタプルを取得 val = min(num, key=lambda x:x[2]) print(val) # (9, 2, 1)
numpy.min()
numpy.min() に配列を渡すと要素の中から最小値を選んで返します。オプション引数 axis に数値を渡すと、指定した軸ごとに最小要素を取り出して 1 次元配列を生成します。
# NUMPY_MIN # In[1] x = np.array([[45, 20, 68], [ 5, 91, 37]]) # 要素の最小値を取得 x_min = np.min(x) # 各列の最小要素を取り出して1次元配列を生成 x_min_0 = np.min(x, axis=0) # 各行の最小要素を取り出して1次元配列を生成 x_min_1 = np.min(x, axis=1) print(x_min) print(x_min_0) print(x_min_1) # 5 # [5 20 37] # [20 5]
keepdims に True を渡すと、もとの配列の次元を保持します。
# In[2] # x = [[45, 20, 68], # [ 5, 91, 37]] # 各行の最小要素を取り出して1次元配列を生成(次元を保持) x_min_1k = np.min(x, axis=1, keepdims=True) print(x_min_1k) # [[20] # [5]]
nan は常に最小値として扱われます。
# In[3] x = np.array([39, 17, np.nan, 51, 43]) x_min = np.min(x) print(x_min) # nan
numpy.nanmin()
numpy.nanmin() は非数 nan を無視して最小要素を float 型で返します。
# NUMPY_NANMIN # In[1] x = np.array([39, 17, np.nan, 51, 43]) x_nanmin = np.nanmin(x) print(x_nanmin) # 17.0
numpy.argmin()
numpy.argmin() は配列の最小要素のインデックスを返します。
# NUMPY_ARGMIN # In[1] x = np.array([81, 25, 41, 96, 58]) # 最小要素のインデックスを取得 x_min = np.argmin(x) print(x_min) # 1
オプション引数 axis を指定すると、軸ごとの最小値のインデックスを格納した新しい配列を生成します。
# In[2] x = np.array([[28, 63, 14], [77, 22, 40]]) # 列ごとの最小要素のインデックスで配列を生成 x_min_0 = np.argmin(x, axis = 0) # 行ごとの最小要素のインデックスで配列を生成 x_min_1 = np.argmin(x, axis = 1) print(x_min_0) print(x_min_1) # [0 1 0] # [2 1]
numpy.minimum()
numpy.minimum(x1, x2) は配列 x1 と配列 x2 の各要素を比較し、大きくないほう(最小値)を要素にもつ新しい配列を返します。x1 と x2 は同じ形状、もしくはブロードキャスト可能な形状でなければなりません。
# NUMPY_MINIMUM # In[1] x = np.array([[53, 7, 21], [32, 14, 50]]) y = np.array([35, 86, 16]) # xとyの1行目を比較して、大きくないほうの要素でzの1行目を生成 # xとyの2行目を比較して、大きくないほうの要素でzの2行目を生成 z = np.minimum(x, y) print(z) # [[35 7 16] # [32 14 16]]
コメント
下記は誤植と思われますので、ご確認ください。
MAXIMUM In[2] プログラムの上の文で、数値 x1 が比較され → 数値 x2 が比較され
NUMPY_MIN In[2] プログラムで、np.max( ) → np.min( ), [[68] [91]] → [[20] [ 5]]
訂正しました。
ありがとうございます。m(_ _)m
NUMPY_MIN In[2] プログラムで、np.max( ) → np.min( ) の修正もお願いいたします。
申し訳ないです。
修正しました。m(_ _)m
【AI連載小説】科学とコードの交差点(32)
「Pythonで最大値(max)を求める色々な方法」
六郷開誠(ろくごう かいせい)は、京都大学理工学部の理論物理学の学生として日々数学とプログラミングに没頭していた。ある日、彼は授業の合間に自身の趣味であるPythonサークルのメンバーたちと共に、リストの最大値を求める方法について熱く議論していた。サークルの部室では、開誠の友人である刑部明信も集まってきた。彼らは気さくに挨拶を交わし、開誠はリストの最大値(max)を求めるプログラムを書き始めた。まず、開誠は普通にforループを使用してリストの最大値を見つける方法を試した。彼はコードを書きながら口に出し、「これなら理解しやすくて良いかもしれない」と言った。
しかし、開誠は冷静になりすぎて、この方法に満足できなかった。彼は他にもっと効率的な方法があるのではないかと考え、刑部明信に向かって言った。「もっとPythonらしい方法があるんじゃないか?」そこで、開誠はリストの最大値を求めるための組み込み関数であるmax()を使ってみることに決めた。彼はニコニコしながら、次のようなコードを書いた。
これに対して刑部明信は笑いながら「やっぱり一番簡単なのが一番いいってことかな。」と言った。しかし、開誠はまだ納得していない様子で、考え込む姿勢を崩さない。すると、開誠は一呼吸おいてから、新たな方法を思いついた。それはリストをソートして最後の要素を取得する方法だった。彼は眼鏡の縁に軽く触れながら、次のようなコードを書いた。
開誠はこれで最大値を求める別のアプローチを見つけたことに満足げな表情を浮かべた。