pandasで行・列ごとの最頻値を取得するmode
pandasでDataFrame
やSeries
の最頻値を取得するにはmode()
メソッドを使う。
ユニークな要素の数や頻度(出現回数)などを取得したい場合は以下の記事を参照。
最頻値を含む要約統計量をまとめて算出したい場合はdescribe()
メソッドが便利。
本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。
import pandas as pd
print(pd.__version__)
# 2.1.4
pandas.Seriesのmode()
Series
のmode()
はSeries
を返す。最頻値が一つだけでもSeries
なので注意。
s = pd.Series(['X', 'X', 'X', 'Y'])
print(s)
# 0 X
# 1 X
# 2 X
# 3 Y
# dtype: object
print(s.mode())
# 0 X
# dtype: object
print(type(s.mode()))
# <class 'pandas.core.series.Series'>
print(s.mode()[0])
# X
print(type(s.mode()[0]))
# <class 'str'>
最頻値が複数ある場合は以下の通り。Series
はtolist()
メソッドでリストに変換可能。
s_multi = pd.Series(['X', 'X', 'Y', 'Y'])
print(s_multi)
# 0 X
# 1 X
# 2 Y
# 3 Y
# dtype: object
print(s_multi.mode())
# 0 X
# 1 Y
# dtype: object
print(s_multi.mode()[0])
# X
print(s_multi.mode().tolist())
# ['X', 'Y']
print(type(s_multi.mode().tolist()))
# <class 'list'>
デフォルトでは欠損値NaN
は除外される。引数dropna
をFalse
とするとNaN
も含めて処理される。
s_nan = pd.Series(['X', float('nan'), float('nan'), float('nan')])
print(s_nan)
# 0 X
# 1 NaN
# 2 NaN
# 3 NaN
# dtype: object
print(s_nan.mode())
# 0 X
# dtype: object
print(s_nan.mode(dropna=False))
# 0 NaN
# dtype: object
pandasにおける欠損値については以下の記事を参照。
pandas.DataFrameのmode()
以下のDataFrame
を例とする。
df = pd.DataFrame({'col1': ['X', 'X', 'X', 'Y'],
'col2': ['X', 'X', 'Y', 'Y']},
index=['row1', 'row2', 'row3', 'row4'])
print(df)
# col1 col2
# row1 X X
# row2 X X
# row3 X Y
# row4 Y Y
列ごとの最頻値を取得
デフォルトではDataFrame
のmode()
メソッドは列ごとの最頻値を要素とするDataFrame
を返す。最頻値が一つだけでも一行のDataFrame
が返される。
列によって最頻値の個数が異なる場合、空き部分は欠損値NaN
となる。
print(df.mode())
# col1 col2
# 0 X X
# 1 NaN Y
print(type(df.mode()))
# <class 'pandas.core.frame.DataFrame'>
各列の最頻値の個数は欠損値NaN
ではない要素の個数をカウントするcount()
メソッドで取得できる。
print(df.mode().count())
# col1 1
# col2 2
# dtype: int64
結果のDataFrame
の一行目が各列の最頻値(複数ある場合はその中の一つ)になる。一行目はiloc[0]
で取得可能。
print(df.mode().iloc[0])
# col1 X
# col2 X
# Name: 0, dtype: object
DataFrame
からmode()
を呼んで列を選択すると欠損値NaN
を含む場合があるが、先に列を選択してからSeries
としてmode()
を呼ぶと欠損値NaN
は含まれない。
print(df.mode()['col1'])
# 0 X
# 1 NaN
# Name: col1, dtype: object
print(df['col1'].mode())
# 0 X
# Name: col1, dtype: object
apply()
メソッドで各列からmode()
を呼んでtolist()
でリスト化すると、最頻値のリストlist
を要素とするSeries
を取得できる。
- 関連記事: pandasで要素・行・列に関数を適用するmap, apply, applymap
- 関連記事: Pythonのlambda(ラムダ式、無名関数)の使い方
- 関連記事: pandasで任意の位置の値を取得・変更するat, iat, loc, iloc
s_list = df.apply(lambda x: x.mode().tolist())
print(s_list)
# col1 [X]
# col2 [X, Y]
# dtype: object
print(s_list.at['col2'])
# ['X', 'Y']
print(type(s_list.at['col2']))
# <class 'list'>
行ごとの最頻値を取得: 引数axis
引数axis
を1
または'columns'
とすると行ごとの最頻値が取得できる。欠損値NaN
ではない要素の個数をカウントするcount()
メソッドにも引数axis
がある。
print(df.mode(axis=1))
# 0 1
# row1 X NaN
# row2 X NaN
# row3 X Y
# row4 Y NaN
print(df.mode(axis=1).count(axis=1))
# row1 1
# row2 1
# row3 2
# row4 1
# dtype: int64
なお、pandasでは列ごとにデータ型dtype
を持ち、基本的には列ごとに同種のデータが並んでいることを前提としている。行ごとに同種のデータが並んでいるのであれば転置したほうがいいかもしれない。
print(df.T)
# row1 row2 row3 row4
# col1 X X X Y
# col2 X X Y Y
print(df.T.mode())
# row1 row2 row3 row4
# 0 X X X Y
# 1 NaN NaN Y NaN
欠損値NaNを含めるか指定: 引数dropna
デフォルトでは欠損値NaN
は除外される。引数dropna
をFalse
とするとNaN
も含めて処理される。
df_nan = df.copy()
df_nan.iloc[1:, 1] = float('nan')
print(df_nan)
# col1 col2
# row1 X X
# row2 X NaN
# row3 X NaN
# row4 Y NaN
print(df_nan.mode())
# col1 col2
# 0 X X
print(df_nan.mode(dropna=False))
# col1 col2
# 0 X NaN
数値列のみを対象とするか指定: 引数numeric_only
デフォルトでは数値列もその他の型の列も処理の対象となる。引数numeric_only
をTrue
とすると数値列のみが対象となる。
df_num = df.copy()
df_num['col3'] = [1, 1, 1, 0]
print(df_num)
# col1 col2 col3
# row1 X X 1
# row2 X X 1
# row3 X Y 1
# row4 Y Y 0
print(df_num.mode())
# col1 col2 col3
# 0 X X 1.0
# 1 NaN Y NaN
print(df_num.mode(numeric_only=True))
# col3
# 0 1
数値列以外のみを対象としたい場合はselect_dtypes()
を使う。
print(df_num.select_dtypes(exclude='number').mode())
# col1 col2
# 0 X X
# 1 NaN Y
最頻値の頻度(出現回数)を取得
最頻値の頻度(出現回数)はSeries
のvalue_counts()
メソッドで取得できる。
value_counts()
は、ユニークな要素の値をインデックス(ラベル)、その個数を要素とするSeries
を返す。デフォルトでは出現回数が多い順にソートされるので、返り値のSeries
の先頭の値が最頻値の頻度となる。
df = pd.DataFrame({'col1': ['X', 'X', 'X', 'Y'],
'col2': ['X', 'X', 'Y', 'Y']},
index=['row1', 'row2', 'row3', 'row4'])
print(df)
# col1 col2
# row1 X X
# row2 X X
# row3 X Y
# row4 Y Y
print(df['col1'].value_counts())
# col1
# X 3
# Y 1
# Name: count, dtype: int64
print(df['col1'].value_counts().iat[0])
# 3
元のSeries
の要素が結果のSeries
のindex
となる。数値がindex
の場合は[番号]
で値を指定するとエラーになるためiat[番号]
を使って厳密に指定している。上の例は文字列なので[番号]
でも問題はない。
- 関連記事: pandasのインデックス指定で行・列を抽出
各列の要約統計量を算出するdescribe()
メソッドでも最頻値とその頻度が求められる。
print(df.describe())
# col1 col2
# count 4 4
# unique 2 2
# top X X
# freq 3 2
項目top
が最頻値でfreq
がその頻度。最頻値が複数ある場合はその中の一つだけが返される。結果はDataFrame
なので、loc
やat
などで行や要素を取得可能。
print(df.describe().loc['freq'])
# col1 3
# col2 2
# Name: freq, dtype: object
print(df.describe().at['freq', 'col2'])
# 2
describe()
には引数axis
はないので、行に対して適用したい場合は転置してから呼ぶ。
print(df.T.describe())
# row1 row2 row3 row4
# count 2 2 2 2
# unique 1 1 2 1
# top X X X Y
# freq 2 2 1 2
describe()
についての詳細は以下の記事を参照。