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=0axis='index'にしても同じ結果が得られます。 axis=1axis='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関数を使うとよいでしょう。

参考