最頻値 (モード)

当サイトではアフィリエイトプログラムを利用して商品を紹介しています。

最頻値 (モード)

ある標本の中で最も頻繁に現れる値を 最頻値 (モード) といいます。たとえば
 
 [1, 2, 5, 5, 5, 8, 8, 12, 19]
 
においては要素 5 が最も多く含まれているので、最頻値は 5 となります。Python では statistics.mode() を使って標本の最頻値を取得できます。

# PYTHON_STATISTICS_MODE

# In[1]

import statistics

x = [1, 2, 5, 5, 5, 8, 8, 12, 19]

# xの最頻値
mode_x = statistics.mode(x)

print("xの最頻値: {:d}".format(mode_x))
# データの最頻値: 5

SciPy パッケージ には、多次元配列の指定軸に沿った最頻値と頻度を取得できる scipy.stats.mode() が用意されています (詳細については記事の後半を参照してください)。

statistics.mode()

statistics.mode(data) は data の最頻値 (モード) を返します。

# In[2]

import statistics

x = [0, 1, 0, 2, 0, 0, 1, 1]

# xの最頻値
mode_x = statistics.mode(x)

print("xの最頻値: {:d}".format(mode_x))
# データの最頻値: 0

最頻値が複数あるデータを渡すと、最初に検出されたモードを返します。たとえば、以下のコードでは、6, 10, 15 をそれぞれ 2 個ずつ含んだリストを渡していますが、インデックスの一番小さい 6 が返ります。

# In[3]

y = [2, 3, 6, 6, 7, 10, 10, 15, 15]

# データの最頻値
mode_y = statistics.mode(y)

print("データの最頻値: {:.1f}".format(mode_y))
# データの最頻値: 6.0

statistics.mode() に文字列を渡せば、単語や文章に最も多く含まれる文字を知ることができます。

# In[4]

my_str = "NumPy is a Base N-dimensional array package."

# my_strに最も多く含まれている文字を取得
statistics.mode(my_str)

# 'a'

scipy.stats.mode()

scipy.stats.mode() は指定軸に沿った最頻値 (モード) と頻度を返します。

scipy.stats.mode(a, axis=0, nan_policy='propagate')

最頻値の候補が複数ある場合、その中の最小値を返します。
例として、次のような 3 行 5 列の 2 次元配列を用意します。

# SCIPY_STATS_MODE

# In[1]

import numpy as np
from scipy import stats

x = np.array([[4, 1, 4, 2, 5],
              [2, 1, 1, 2, 5],
              [1, 1, 5, 1, 1]])

axis=0 (デフォルト設定) のときは、列ごとの最頻値を返します

# In[2]

# 列ごとの最頻値と頻度
mode_1, count_1 = stats.mode(x, axis=0)

print("列ごとの最頻値と頻度:\n{0}\n{1}".format(mode_1, count_1))

# 列ごとの最頻値と頻度:
# [[1 1 1 2 5]]
# [[1 3 1 2 2]]

axis=1 ならば行ごとに最頻値を返します。

# In[3]

# 行ごとの最頻値と頻度
mode_2, count_2 = stats.mode(x, axis=1)

print("行ごとの最頻値と頻度:\n{0}\n\n{1}".format(mode_2, count_2))

'''行ごとの最頻値と頻度:
[[4]
 [1]
 [1]]

[[2]
 [2]
 [4]]'''

axis=None を指定すると、すべての要素を対象に最頻値を求めます。

# In[4]

# 全要素の最頻値と頻度
mode_3, count_3 = stats.mode(x, axis=None)

print("全要素の最頻値と頻度:\n{0}\n{1}".format(mode_3, count_3))

# 全要素の最頻値と頻度:
# [1]
# [7]

コメント

  1. HNaito より:

    下記は誤植と思われますので、ご確認ください。
    STATISTICS_MODE-2 プログラムで、mode_x = → mode_y =
    Python 3.8以上では StatisticsError は発生せずに、最初に出現した値、あるいは複数の値を返すようです。

    • あとりえこばと より:

      STATISTICS_MODE-2 の動作を再確認しました。
      確かに StatisticsError は発生せずに 6 が返りました。
      最新の情報をありがとうございました!

  2. あとりえこばと より:

    【AI連載小説】科学とコードの交差点(20)「collections.Counterで最頻値を計算します」
     
    ある日、六郷開誠の家に刑部明信が訪れ、Pythonに関する議論が繰り広げられた。開誠は新しいデータ解析の課題に直面しており、最頻値を求める方法についてのアイデアを共有したいと思っていた。

    開誠(Kaisei): お疲れさま、明信。ちょうど最近、データ解析の中で最頻値を求める必要があるんだ。どんな方法があると思う?
    明信(Akinobu): それは面白そうだね。最頻値を求めるにはいくつかの方法があるよ。まず、statisticsモジュールのmode()関数を使うのが一つの手だよ。
    開誠: ああ、statisticsモジュールか。それは便利そうだね。でも、もう少し詳しく教えてくれる?
    明信: もちろんだ。mode()関数は、与えられたデータから最頻値を見つけ出してくれる。ただし、最頻値が複数ある場合もあるし、ない場合もあるから注意が必要だよ。
    開誠: なるほど。他にも方法はあるのかな?
    明信: そうだね。もしstatisticsモジュールが不便だと感じたら、numpyのmode()関数も使えるよ。ただし、numpyを使う場合は配列が必要だから、データをリストからnumpyの配列に変換する必要がある。
    開誠: なるほど、numpyも覚えておこう。他にも何かオススメの方法はある?
    明信: それから、collectionsモジュールのCounterクラスを使っても最頻値を求めることができる。これは特に頻度分布を取りたい場合に便利だよ。

    明信と開誠は、最頻値を求めるためにcollectionsモジュールのCounterクラスを使って実際にコードを書いてみることに決めた。リビングのテーブルに座り、開誠のノートパソコンを開いて、Pythonコードを書く雰囲気が広がっていた。

    開誠: さて、まずはcollectionsモジュールをインポートしようか。

    from collections import Counter

    明信(Akinobu): そうだね。そして、データを用意しよう。例えばこれでどうかな?

    data = [1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5]

    開誠: いいね。これでCounterクラスにデータを渡して、最頻値を求めてみよう。

    counter = Counter(data)
    mode_result = counter.most_common(1)

    明信: most_common(1)を使うことで最頻値を取得できるんだね。
    開誠: そう。それではmode_resultを表示してみよう。

    print("最頻値:", mode_result[0][0])

    明信: わかった。これで実行してみよう。
     
    開誠がコードを実行すると、最頻値が表示された。
     
    開誠: 簡単だね。これで最頻値を求める準備が整ったよ。