PandasにはNumPyと同様に最大値、最小値を抜き出す関数max
関数とmin
関数があります。
今回は
- describe 属性(attribute)を使った最大値、最小値の取得
- max関数の使い方
- min関数の使い方
について解説します。
max
関数もmin
関数もDataFrameとSeriesのどちらにも適用可能ですが、今回はDataFrameに適用されるものを中心に解説していきます。
describe関数を用いた最大値、最小値の取得
もっとも手軽で、他の情報も簡単に取得できる方法として、DataFrameやSeriesのdescribe
属性を使うものがあります。
deescribe
属性は数値データに対してのみ有効で、最大値、最小値以外にも平均値や標準偏差、データ数、四分位数などを表示してくれます。
詳しい使い方は以下の記事で解説しています。
PandasでDataFrameやSeriesの統計情報を表示するdescribe関数の使い方 /features/pandas-describe.html
簡単なDataFrameを作成してdescribe関数でデータの概要を取得します。
In [1]: import pandas as pd
In [2]: df = pd.DataFrame({
...: "A": [1, -1, 0, 9, 8, 1, -10],
...: "B": [-1, 0, 7, 6, 1, 3, 2],
...: "C": ['A','B','c','D','C','a','b']
...: })
In [3]: df.describe() # 関数なので()をつけるのを忘れずに
Out[3]:
A B
count 7.000000 7.000000
mean 1.142857 2.571429
std 6.309479 2.992053
min -10.000000 -1.000000
25% -0.500000 0.500000
50% 1.000000 2.000000
75% 4.500000 4.500000
max 9.000000 7.000000
In [4]: df['A'].describe() # 特定のカラムに対しても有効
Out[4]:
count 7.000000
mean 1.142857
std 6.309479
min -10.000000
25% -0.500000
50% 1.000000
75% 4.500000
max 9.000000
Name: A, dtype: float64
このように、最大値と最小値を一度に獲得してくれるのでかなり便利です。
カラムごとのデータを知りたいときで特別な条件設定がいらない場合はdescribe
関数を使うことをおすすめします。
max関数
次は最大値を取得してくれるmax
関数です。
APIドキュメントから見ていきます。
APIドキュメント
pandas.DataFrame.max(axis=None,skipna=None,level=None,numeric_only=None, **kwargs)
params:
パラメータ名 | 型 | 概要 |
---|---|---|
axis | 0または’index’ 1または’columns’ |
(省略可能)初期値None 列データ(0または’index’)の中での最大値を取得するか、行データ(1または’columns’)の中での最大値を取得するかを指定します。デフォルトでNoneとなっていますが列データから取得しています。 |
skipna | bool値 | (省略可能)初期値True NaN値を飛ばして最大値を返すかどうかを指定します。 |
level | intもしくは階層の名称 | (省略可能)初期値None ラベルがMultiIndexだった場合、指定された階層のラベルに沿って最大値を返します。このときSeries形式で分割されて返されます。 |
numeric_only | bool値 | (省略可能)初期値None 数値データのみのデータの最大値を抜き出すかどうかを指定します。Noneの場合、数値データ以外のデータも利用しようと試みます。Series形式のデータに対してはこの引数は無効です。 |
returns:
最大値を含んだSeriesかDataFrame(MultiIndexでlevelを指定した場合)
axis
引数で列データと行データ、どちらの最大値を返すかを指定します。残念ながらこの関数でDataFrame全体での最大値を返すようにすることはできません。
MultiIndexがラベルのとき、扱いが少し難しくなりますがそれ以外の場合に対しては素直に引数を指定していけば問題ないでしょう。
サンプルコード
先ほどのデータを使って最大値を求めていきます。
In [21]: df # このデータを使う
Out[21]:
A B C
0 1 -1 A
1 -1 0 B
2 0 7 c
3 9 6 D
4 8 1 C
5 1 3 a
6 -10 2 b
まずは特に引数を指定せずに使ってみます。
In [22]: df.max() # 列ごとの最大値が返される
Out[22]:
A 9
B 7
C c
dtype: object
文字列データだけのC列でも最大値なるものを返しています。
最大値はデータを昇順に並べ替えたときに最後にくる値を抜き出していると読み換えると'c'
が最大値として返された理由が分かります。文字にsort関数を適用したときの挙動と同様になります。
実際に要素を並べ替えてみます。
In [23]: df['A'].sort_values()
Out[23]:
6 -10
1 -1
2 0
0 1
5 1
4 8
3 9
Name: A, dtype: int64
In [24]: df['B'].sort_values()
Out[24]:
0 -1
1 0
4 1
6 2
5 3
3 6
2 7
Name: B, dtype: int64
In [25]: df['C'].sort_values()
Out[25]:
0 A
1 B
4 C
3 D
5 a
6 b
2 c
Name: C, dtype: object
先ほどのmax
関数の出力と見比べてみると、ソートした値の最後尾にあたる値が返ってきてることがわかります。
sort_values
関数の詳しい使い方はこちら。
Pandasで列データをソートするsort_values関数の使い方 /features/pandas-sort-values.html
axis=0
かaxis='index'
にしても同じ結果が得られます。
axis=1
かaxis='columns'
にすると挙動が変わります。
In [26]: df.max(axis=0) # df.max()と同じ結果になる
Out[26]:
A 9
B 7
C c
dtype: object
In [27]: df.max(axis='columns') # 行ごとの最大値を返す
Out[27]:
0 1
1 0
2 7
3 9
4 8
5 3
6 2
dtype: int64
axis='columns' or 1
で指定すると行ごとの最大値を返すことになります。このとき、今回使ったデータには数値データと文字データの両方が含まれることになります。そうすると、文字データは無視され、数値データにおける最大値が返されます。
次にskipna
を指定します。
In [8]: import numpy as np # NaN値を代入するためにNumPyをインポートする
In [29]: df.iloc[3,0] = np.nan
In [31]: df.iloc[3,2] = np.nan
In [32]: df
Out[32]:
A B C
0 1.0 -1 A
1 -1.0 0 B
2 0.0 7 c
3 NaN 6 NaN
4 8.0 1 C
5 1.0 3 a
6 -10.0 2 b
まずはデフォルトであるskipna=True
で最大値を取得すると、先ほどまで文字データだった’C’列に数値データが入り込み、最大値を返されなくなります。
In [33]: df.max()
Out[33]:
A 8.0
B 7.0
dtype: float64
skipna=False
にしてみるとNaN値が最大値となってしまいます。
In [34]: df.max(skipna=False)
Out[34]:
A NaN
B 7.0
dtype: float64
次にnumeric_only
引数を使っていきます。
一旦文字列データに統一するためにfillna
関数を使ってNaN値のところを”missing”という文字列に変換します。
In [37]: df['C'] = df['C'].fillna("missing")
In [38]: df
Out[38]:
A B C
0 1.0 -1 A
1 -1.0 0 B
2 0.0 7 c
3 NaN 6 missing
4 8.0 1 C
5 1.0 3 a
6 -10.0 2 b
In [39]: df.max(numeric_only=True)
Out[39]:
A 8.0
B 7.0
dtype: float64
In [41]: df.max(numeric_only=False)
Out[41]:
A 8
B 7
C missing
dtype: object
次にMultiIndexのラベルを持つDataFrameについて扱っていきます。
In [45]: df.columns = pd.MultiIndex.from_tuples([('foo',0),('foo',1),('bar',1)],
...: names=['A','B']) # MultiIndexの作成
In [46]: df
Out[46]:
A foo bar
B 0 1 1
0 1.0 -1 A
1 -1.0 0 B
2 0.0 7 c
3 NaN 6 missing
4 8.0 1 C
5 1.0 3 a
6 -10.0 2 b
データの中身は以下のようになっています。
A | foo | bar | |
---|---|---|---|
B | 0 | 1 | 1 |
0 | 1.0 | -1 | A |
1 | -1.0 | 0 | B |
2 | 0.0 | 7 | c |
3 | NaN | 6 | missing |
4 | 8.0 | 1 | C |
5 | 1.0 | 3 | a |
6 | -10.0 | 2 | b |
ではこれの最大値を行ごとに取得します。
In [49]: df.max(axis=1)
Out[49]:
0 1.0
1 0.0
2 7.0
3 6.0
4 8.0
5 3.0
6 2.0
dtype: float64
では次にlevel
を指定します。
In [50]: df.max(axis=1,level='A') # fooとbarラベルがついたものごとに最大値を返す
Out[50]:
A foo bar
0 1.0 A
1 0.0 B
2 7.0 c
3 6.0 missing
4 8.0 C
5 3.0 a
6 2.0 b
In [52]: df.max(axis=1,level='B')
Out[52]:
B 0 1
0 1.0 -1
1 -1.0 0
2 0.0 7
3 NaN 6
4 8.0 1
5 1.0 3
6 -10.0 2
このように、level
を指定するとlevel
におけるラベルごとに最大値が返されるようになります。
min関数
使い方などはmax関数と一致しており、返す値だけが異なる関数となります。 ここではAPIドキュメントとサンプルコードを載せておきます。
APIドキュメント
pandas.DataFrame.min(axis=None,skipna=None,numeric_only=None,kwargs)**
params:
パラメータ名 | 型 | 概要 |
---|---|---|
axis | 0または’index’ 1または’columns’ |
(省略可能)初期値None 列データ(0または’index’)の中での最小値を取得するか、行データ(1または’columns’)の中での最小値を取得するかを指定します。デフォルトでNoneとなっていますが列データから取得しています。 |
skipna | bool値 | (省略可能)初期値True NaN値を飛ばして最小値を返すかどうかを指定します。 |
level | intもしくは階層の名称 | (省略可能)初期値None ラベルがMultiIndexだった場合、指定された階層のラベルに沿って最小値を返します。このときSeries形式で分割されて返されます。 |
numeric_only | bool値 | (省略可能)初期値None 数値データのみのデータの最小値を抜き出すかどうかを指定します。Noneの場合、数値データ以外のデータも利用しようと試みます。Series形式のデータに対してはこの引数は無効です。 |
returns:
最小値を含んだSeriesかDataFrame(MultiIndexでlevelを指定した場合)
サンプルコード
max
関数で扱った内容をそのままmin
関数に置き換えて実行しています。
In [53]: df = pd.DataFrame({
...: "A":[1,-1,0,9,8,1,-10],
...: "B":[-1,0,7,6,1,3,2],
...: "C":["A","B","c","D","C","a","b"]})
...:
In [54]: df
Out[54]:
A B C
0 1 -1 A
1 -1 0 B
2 0 7 c
3 9 6 D
4 8 1 C
5 1 3 a
6 -10 2 b
In [55]: df.min() # 特に引数を指定しないで最小値を取得
Out[55]:
A -10
B -1
C A
dtype: object
axis
を指定します。
In [56]: df.min(axis=0) # デフォルトと同様
Out[56]:
A -10
B -1
C A
dtype: object
In [57]: df.min(axis=1) # 行ごとの最小値
Out[57]:
0 -1
1 -1
2 0
3 6
4 1
5 1
6 -10
dtype: int64
次にskipna
です。
In [58]: df.iloc[3,0] = np.nan
In [59]: df.iloc[3,2] = np.nan
In [60]: df
Out[60]:
A B C
0 1.0 -1 A
1 -1.0 0 B
2 0.0 7 c
3 NaN 6 NaN
4 8.0 1 C
5 1.0 3 a
6 -10.0 2 b
In [61]: df.min() # デフォルトではskipna=True
Out[61]:
A -10.0
B -1.0
dtype: float64
In [62]: df.min(skipna=False) # Falseにしてみる
Out[62]:
A NaN
B -1.0
dtype: float64
numeric_onlyの値をいじります。
In [63]: df['C'] = df['C'].fillna('missing') # 欠損値を"mising"に置き換える
In [64]: df
Out[64]:
A B C
0 1.0 -1 A
1 -1.0 0 B
2 0.0 7 c
3 NaN 6 missing
4 8.0 1 C
5 1.0 3 a
6 -10.0 2 b
In [66]: df.min(numeric_only=True)
Out[66]:
A -10.0
B -1.0
dtype: float64
In [67]: df.min(numeric_only=False)
Out[67]:
A -10
B -1
C A
dtype: object
MultiIndexでlevel
を指定します。
In [68]: df.columns = pd.MultiIndex.from_tuples([('foo',0),('foo',1),('bar',1)]
...: ,names=['A','B']) # MultiIndexの作成
In [69]: df
Out[69]:
A foo bar
B 0 1 1
0 1.0 -1 A
1 -1.0 0 B
2 0.0 7 c
3 NaN 6 missing
4 8.0 1 C
5 1.0 3 a
6 -10.0 2 b
In [70]: df.min(axis=1)
Out[70]:
0 -1.0
1 -1.0
2 0.0
3 6.0
4 1.0
5 1.0
6 -10.0
dtype: float64
In [71]: df.min(axis=1,level='A')
Out[71]:
A foo bar
0 -1.0 A
1 -1.0 B
2 0.0 c
3 6.0 missing
4 1.0 C
5 1.0 a
6 -10.0 b
In [72]: df.min(axis=1,level='B')
Out[72]:
B 0 1
0 1.0 -1
1 -1.0 0
2 0.0 7
3 NaN 6
4 8.0 1
5 1.0 3
6 -10.0 2
まとめ
今回は、最大値と最小値とを抜き出す方法をまとめました。
細かい指定などなくとりあえず最大値と最小値を知りたいときはdescribe
関数で十分ですが、いくつかの条件設定をしたいときやインデックスラベルに応じた検索範囲の指定をしたいときはmax, min関数が便利なので、特にMultiIndexのときはmax
関数やmin
関数を使うとよいでしょう。