pandasでn個の最大値・最小値を取得(nlargest, nsmallest)
pandas.DataFrame
, Series
からn個の最大値・最小値(大きい方からn個、小さい方からn個)を含む行・要素を取得するには、nlargest()
, nsmallest()
メソッドを使う。
- pandas.DataFrame.nlargest — pandas 1.0.4 documentation
- pandas.DataFrame.nsmallest — pandas 1.0.4 documentation
- pandas.Series.nlargest — pandas 1.0.4 documentation
- pandas.Series.nsmallest — pandas 1.0.4 documentation
ここでは以下の内容について説明する。
- 最大値・最小値の取得:
max()
,min()
nlargest()
,nsmallest()
の基本的な使い方pandas.Series
の場合pandas.DataFrame
の場合
- 重複した値の処理: 引数
keep
- n個の最大値・最小値をリストやNumPy配列
ndarray
で取得 pandas.DataFrame
のすべての列に対して一括処理
最大値や最小値となる要素の行名を取得したい場合や、pandas.DataFrame
, Series
全体を昇順・降順にソートしたい場合は以下の記事を参照。
- 関連記事: pandasで最大値・最小値の行名・列名を取得するidxmax, idxmin
- 関連記事: pandas.DataFrame, Seriesをソートするsort_values, sort_index
また、Python組み込みのリストに対して最大値・最小値をn個取得したい場合は以下の記事を参照。
以降のサンプルコードでは以下のpandas.DataFrame
およびpandas.Series
を例として使う。
import pandas as pd
import numpy as np
df = pd.DataFrame({'col1': [2, 3, 1, 3, 3, 4],
'col2': [30, 10, 10, 40, 40, 20]},
index=['A', 'B', 'C', 'D', 'E', 'F'])
print(df)
# col1 col2
# A 2 30
# B 3 10
# C 1 10
# D 3 40
# E 3 40
# F 4 20
s = df['col1']
print(s)
# A 2
# B 3
# C 1
# D 3
# E 3
# F 4
# Name: col1, dtype: int64
最大値・最小値の取得: max(), min()
最大値・最小値のみ(1個だけ)を取得したい場合はmax()
, min()
メソッドを使う。
pandas.DataFrame
に対しては、各列の最大値・最小値を要素とするpandas.Series
が返される。
print(df.max())
# col1 4
# col2 40
# dtype: int64
print(type(df.max()))
# <class 'pandas.core.series.Series'>
print(df.min())
# col1 1
# col2 10
# dtype: int64
print(type(df.min()))
# <class 'pandas.core.series.Series'>
引数axis
を1
とすると各行の最大値・最小値となる。
print(df.max(axis=1))
# A 30
# B 10
# C 10
# D 40
# E 40
# F 20
# dtype: int64
print(df.min(axis=1))
# A 2
# B 3
# C 1
# D 3
# E 3
# F 4
# dtype: int64
pandas.Series
に対しては、要素の値(スカラー値)が返される。
print(s.max())
# 4
print(type(s.max()))
# <class 'numpy.int64'>
print(s.min())
# 1
print(type(s.min()))
# <class 'numpy.int64'>
nlargest(), nsmallest()の基本的な使い方
n個の最大値・最小値(大きい方からn個、小さい方からn個)を取得するにはnlargest()
, nsmallest()
メソッドを使う。該当する値が重複して存在する場合の処理については後述。
pandas.Seriesの場合
第一引数n
に個数を指定する。大きい方からn個、または、小さい方からn個を要素とするpandas.Series
が返される。
print(s.nlargest(4))
# F 4
# B 3
# D 3
# E 3
# Name: col1, dtype: int64
print(type(s.nlargest(4)))
# <class 'pandas.core.series.Series'>
print(s.nsmallest(4))
# C 1
# A 2
# B 3
# D 3
# Name: col1, dtype: int64
print(type(s.nsmallest(4)))
# <class 'pandas.core.series.Series'>
n=1
の場合も、要素数が1個のpandas.Series
となる。
print(s.nlargest(1))
# F 4
# Name: col1, dtype: int64
print(type(s.nlargest(1)))
# <class 'pandas.core.series.Series'>
同様の処理は.sort_values(ascending=False).head(n)
, .sort_values().head(n)
でも可能だが、n
がpandas.Series
全体の要素数に比べて小さい場合はnlargest()
, nsmallest()
のほうが高速とのこと。
Faster than .sort_values(ascending=False).head(n) for small n relative to the size of the Series object. pandas.Series.nlargest — pandas 1.0.4 documentation
Faster than .sort_values().head(n) for small n relative to the size of the Series object. pandas.Series.nsmallest — pandas 1.0.4 documentation
sort_values()
, head()
については以下の記事を参照。
- 関連記事: pandas.DataFrame, Seriesをソートするsort_values, sort_index
- 関連記事: pandas.DataFrame, Seriesの先頭・末尾の行を返すheadとtail
pandas.DataFrameの場合
pandas.DataFrame
の場合、第一引数n
に個数、第二引数columns
に列名を指定する。指定した列の大きい方からn個、または、小さい方からn個を含む行のpandas.DataFrame
が返される。
print(df.nlargest(4, 'col1'))
# col1 col2
# F 4 20
# B 3 10
# D 3 40
# E 3 40
print(type(df.nlargest(4, 'col1')))
# <class 'pandas.core.frame.DataFrame'>
print(df.nsmallest(4, 'col1'))
# col1 col2
# C 1 10
# A 2 30
# B 3 10
# D 3 40
print(type(df.nsmallest(4, 'col1')))
# <class 'pandas.core.frame.DataFrame'>
n=1
の場合も、1行のpandas.DataFrame
。
print(df.nlargest(1, 'col1'))
# col1 col2
# F 4 20
print(type(df.nlargest(1, 'col1')))
# <class 'pandas.core.frame.DataFrame'>
第二引数columns
には列名のリストも指定可能。
リストの後ろの列から順にソートして、上からn行を返すイメージ。最終結果はリストの最初に指定した列が降順(nlargest()
)または昇順(nsmallest()
)に並ぶ。
print(df.nlargest(4, ['col1', 'col2']))
# col1 col2
# F 4 20
# D 3 40
# E 3 40
# B 3 10
print(df.nlargest(4, ['col2', 'col1']))
# col1 col2
# D 3 40
# E 3 40
# A 2 30
# F 4 20
各列が独立にソートされるわけではないので注意。各列それぞれの最大値・最小値をn個取得する例は後述。
df.sort_values(columns, ascending=False)
, df.sort_values(columns, ascending=True).head(n)
と同等だが、nlargest()
, nsmallest()
のほうが効率がよい(performant)とのこと。
This method is equivalent to df.sort_values(columns, ascending=False).head(n), but more performant. pandas.DataFrame.nlargest — pandas 1.0.4 documentation
This method is equivalent to df.sort_values(columns, ascending=True).head(n), but more performant. pandas.DataFrame.nsmallest — pandas 1.0.4 documentation
pandas.Series
のようにn
と行数との関係は示されていない。処理速度が重要な場合は、実際に実行する条件で処理時間を計測してみるといいかもしれない。
重複した値の処理: 引数keep
nlargest()
, nsmallest()
において、該当する値が重複して存在する場合の処理は引数keep
で指定可能。引数keep
はpandas0.24.0
で追加。それより前のバージョンでは使えない。
以下の例はpandas.DataFrame
のnsmallest()
だが、pandas.Series
やnlargest()
でも考え方は同じ。
デフォルトはkeep='first'
で、元のpandas.DataFrame
またはpandas.Series
で上にある行・要素が優先される(上から順に残る)。
print(df.nsmallest(4, 'col1'))
# col1 col2
# C 1 10
# A 2 30
# B 3 10
# D 3 40
print(df.nsmallest(4, 'col1', keep='first'))
# col1 col2
# C 1 10
# A 2 30
# B 3 10
# D 3 40
keep='last'
とすると、下にある行・要素が優先される(下から順に残る)。
print(df.nsmallest(4, 'col1', keep='last'))
# col1 col2
# C 1 10
# A 2 30
# E 3 40
# D 3 40
keep='all'
とすると、重複する行・要素すべてが残る。
print(df.nsmallest(4, 'col1', keep='all'))
# col1 col2
# C 1 10
# A 2 30
# B 3 10
# D 3 40
# E 3 40
pandas.DataFrame
において引数columns
をリストで指定した場合、各列の要素がすべて一致しているときのみ重複しているとみなされる。いずれかの列のみが同じでも重複しているとはみなされないので注意。
print(df.nsmallest(3, ['col1', 'col2'], keep='all'))
# col1 col2
# C 1 10
# A 2 30
# B 3 10
print(df.nsmallest(4, ['col1', 'col2'], keep='all'))
# col1 col2
# C 1 10
# A 2 30
# B 3 10
# D 3 40
# E 3 40
n個の最大値・最小値をリストやNumPy配列ndarrayで取得
pandas.DataFrame
の任意の列(= pandas.Series
)のn個の最大値・最小値をリストで取得したい場合はtolist()
を使う。
print(df['col1'].nsmallest(4).tolist())
# [1, 2, 3, 3]
print(type(df['col1'].nsmallest(4).tolist()))
# <class 'list'>
NumPy配列ndarray
で取得したい場合はto_numpy()
またはvalues
を使う(to_numpy()
はpandas0.24.0
で追加)。
print(df['col1'].nsmallest(4).to_numpy())
# [1 2 3 3]
print(type(df['col1'].nsmallest(4).to_numpy()))
# <class 'numpy.ndarray'>
print(df['col1'].nsmallest(4).values)
# [1 2 3 3]
print(type(df['col1'].nsmallest(4).values))
# <class 'numpy.ndarray'>
pandas.DataFrameのすべての列に対して一括処理
pandas.DataFrame
のすべての列のn個の最大値・最小値を一括で取得する例は以下の通り。
ここでは、結果をリスト、辞書(キーが列名)、numpy.ndarray
としている。
print(df['col1'].nsmallest(3))
# C 1
# A 2
# B 3
# Name: col1, dtype: int64
print(df['col2'].nsmallest(3))
# B 10
# C 10
# F 20
# Name: col2, dtype: int64
print([df[col_name].nsmallest(3).tolist() for col_name in df])
# [[1, 2, 3], [10, 10, 20]]
print({col_name: col.nsmallest(3).tolist() for col_name, col in df.iteritems()})
# {'col1': [1, 2, 3], 'col2': [10, 10, 20]}
print(np.array([df[col_name].nsmallest(3).tolist() for col_name in df]))
# [[ 1 2 3]
# [10 10 20]]
pandas.DataFrame
のイテレーション、および、リスト内包表記、辞書内包表記、リストからnumpy.ndarray
への変換を利用している。
- 関連記事: pandas.DataFrameのforループ処理(イテレーション)
- 関連記事: Pythonリスト内包表記の使い方
- 関連記事: Pythonで辞書を作成するdict()と波括弧、辞書内包表記
- 関連記事: NumPy配列ndarrayとPython標準のリストを相互に変換
なお、keep='all'
として各列の要素数が異なる場合、numpy.ndarray
にはそのまま変換できないので注意。
print([df[col_name].nsmallest(3, keep='all').tolist() for col_name in df])
# [[1, 2, 3, 3, 3], [10, 10, 20]]
print({col_name: col.nsmallest(3, keep='all').tolist() for col_name, col in df.iteritems()})
# {'col1': [1, 2, 3, 3, 3], 'col2': [10, 10, 20]}
print(np.array([df[col_name].nsmallest(3, keep='all').tolist() for col_name in df]))
# [list([1, 2, 3, 3, 3]) list([10, 10, 20])]