Pythonで辞書の値の最大値・最小値とそのキーを取得
Pythonで辞書(dict型オブジェクト)の値valueの最大値・最小値およびそのキーkeyを取得する方法を説明する。
辞書のキー(key)の最大値・最小値を取得
イテラブルオブジェクトの最大・最小の要素を返す関数max(), min()に辞書オブジェクトを渡すと、キーkeyの最大値・最小値が返る。これは、辞書はイテラブルオブジェクトとして要素のキーを列挙するため。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
print(max(d))
# e
print(min(d))
# a
なお、文字列の大小関係はアルファベット順で比較される。
辞書の値(value)の最大値・最小値を取得
辞書のvalues()メソッドは辞書の値valueのビューを返す。
これをmax(), min()に渡すと、辞書の値の最大値・最小値が取得できる。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
print(max(d.values()))
# 100
print(min(d.values()))
# 20
辞書の値が最大・最小となるキーを取得
辞書の値が最大・最小となるキーは以下のように取得できる。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
print(max(d, key=d.get))
# a
print(min(d, key=d.get))
# b
max(), min()の引数keyには、各要素が比較される前に適用される呼び出し可能オブジェクト(関数など)を指定する。これにより、各要素そのものではなく引数keyに指定した関数などの結果を比較して最大値・最小値が算出される。
ここでは引数keyに元の辞書オブジェクトのget()メソッドを指定している。get()はキーからその値を返すメソッド。
上述のように辞書は要素のキーkeyを列挙する。そのキーを引数としてget()メソッドを適用することで値valueが返され、それに従って最大値・最小値が算出される。
辞書の値が最大・最小となるキーと値を同時に取得
辞書の値が最大・最小となるキーと値を同時に取得したい場合は、辞書のitems()メソッドを使う。items()メソッドは辞書のキーと値のタプル(key, value)のビューを返す。
max(), min()の引数keyにタプルの2要素目(= 値value)を取得するラムダ式(無名関数)を指定すると、値valueに従って最大値・最小値が求められる。
ラムダ式については以下の記事を参照。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
print(max(d.items(), key=lambda x: x[1]))
# ('a', 100)
print(min(d.items(), key=lambda x: x[1]))
# ('b', 20)
タプルのアンパックを利用して、それぞれ別々の変数に代入することもできる。
max_k, max_v = max(d.items(), key=lambda x: x[1])
print(max_k)
# a
print(max_v)
# 100
ラムダ式ではなく標準ライブラリoperatorのitemgetter()を利用する方法もある。以下の記事を参照。
最大・最小となる値が複数存在する場合
これまでの例では、最大・最小となる値valueが複数存在する場合、その中のどれか一つのキーkeyまたはキーと値のタプルが返されていた。
リスト内包表記を使うことで、最大・最小となる値valueが複数存在する場合、そのキーまたはキーと値のタプルをリストとして取得できる。
- 関連記事: Pythonリスト内包表記の使い方
キーと値のタプルを取得する例。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
print([kv for kv in d.items() if kv[1] == max(d.values())])
# [('a', 100), ('d', 100)]
キーのみのリストを取得する例。
print([kv[0] for kv in d.items() if kv[1] == max(d.values())])
# ['a', 'd']
この方法だと、最大・最小となる値valueが一つだけの場合も要素数が1のリストが返される。
print([kv for kv in d.items() if kv[1] == min(d.values())])
# [('b', 20)]
pandas.Seriesに変換して処理
辞書をpandas.Seriesに変換してから処理することも可能。
コンストラクタpd.Series()に辞書を指定するとキーがindex、値がvaluesのpandas.Seriesが生成される。
import pandas as pd
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
s = pd.Series(d)
print(s)
# a 100
# b 20
# c 50
# d 100
# e 80
# dtype: int64
print(s.index)
# Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
print(s.values)
# [100 20 50 100 80]
辞書の値(value)の最大値・最小値を取得
pandas.Seriesのメソッドmax(), min()で元の辞書の値valueの最大値・最小値を取得できる。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
s = pd.Series(d)
print(s.max())
# 100
print(s.min())
# 20
辞書のキー(key)の最大値・最小値を取得
pandas.Seriesのindexの最大値・最小値が元の辞書のキーkeyの最大値・最小値となる。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
s = pd.Series(d)
print(max(s.index))
# e
print(min(s.index))
# a
辞書の値が最大・最小となるキーを取得
pandas.Seriesのメソッドidxmax(), idxmin()で元の辞書の値が最大・最小となるキーを取得できる。最大値・最小値が複数ある場合は最初のキーのみが返される。
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
s = pd.Series(d)
print(s.idxmax())
# a
print(s.idxmin())
# b
最大値・最小値が複数ある場合にすべてのキーを取得したい場合は、最大値・最小値に等しい要素をブールインデックス参照で抽出し、index属性を取得する。
print(s[s == s.max()])
# a 100
# d 100
# dtype: int64
print(s[s == s.max()].index)
# Index(['a', 'd'], dtype='object')
リスト型にしたい場合はIndexのtolist()メソッドかlist()を使う。
print(s[s == s.max()].index.tolist())
# ['a', 'd']
print(list(s[s == s.max()].index))
# ['a', 'd']
最小値の場合も同様。この方法の場合、該当するキーが一つだけの場合もIndexやリストで返される。
print(s[s == s.min()])
# b 20
# dtype: int64
print(s[s == s.min()].index)
# Index(['b'], dtype='object')
print(s[s == s.min()].index.tolist())
# ['b']
print(list(s[s == s.min()].index))
# ['b']
その他の処理
辞書をpandas.Seriesに変換すると、ソートや条件抽出などをするのも簡単で便利。
- 関連記事: pandas.DataFrame, Seriesをソートするsort_values, sort_index
- 関連記事: pandasで複数条件のAND, OR, NOTから行を抽出(選択)
d = {'a': 100, 'b': 20, 'c': 50, 'd': 100, 'e': 80}
s = pd.Series(d)
print(s.sort_values())
# b 20
# c 50
# e 80
# a 100
# d 100
# dtype: int64
print(s[s > 60])
# a 100
# d 100
# e 80
# dtype: int64