Rで最頻値(mode)を求める ~連続値データの場合~

Rで最頻値を求める方法として、よく見かけるのがtable関数を使った方法です↓

names(which.max(table(x)))

離散値データの場合は上記でうまくいくのですが、連続値データの場合はうまくいきません。

また離散値データであっても、取りうる値の種類に対してサンプルサイズが小さい場合もうまくいきません。

具体例をあげてみます。40人学級でのテストの点数をイメージしました。

# テストの点数っぽいサンプルデータを作る
set.seed(4) # (やや恣意的な)再現性のために
x <- round(rnorm(n=40, mean=50, sd=15))
x


 [1] 53 42 63 59 75 60 31 47 78 77 58 50 56 49 51 53 67 49 48 46
[21] 73 52 70 69 59 46 69 64 36 69 52 66 39 28 63 44 47 64 43 40


上記データに対して、tableを使って最頻値を求めると、

names(which.max(table(x)))

[1] "69"

想定している、"50"とかなりずれた値が出てしまいました。実現値がスパースなので、個別に最も現れた値を出すことに意味がないんですね。

↓階級を1点刻みにしたヒストグラムで見るとよく分かります。

# 1点刻みでヒストグラムを描く
hist(x, breaks=seq(20,80,1))


69点を取った人は3人で最も多いですが、たまたま感がありますよね。50点の周辺の方が頻度が高いように思えます。

すなおに階級に幅を持たせると、予想と近い最頻値が得られます。

# 階級幅はデフォルト(hist関数にまかせる)
hist(x)


上記の場合、40~50の階級が最も度数が多いので、この中間値を階級値として「最頻値は45である」という結論は直感に反していないと思われます。

階級値をきりのいい数字にしたい場合は、↓breaksを指定してやればOKです。

hist(x, breaks=seq(25, 85, 10))



最頻値は50の階級であるという、予想通りの結果となりました。

つまり、連続値(やそれに近い離散値)における最頻値を求めるとは、ヒストグラムを描いてその峰になっているところを求めるということであり、tableを使った方法だとうまくいかない。

というのが、長い前置きでした。

で、ヒストグラムの峰の階級値を知るには、hist関数の戻り値に入っている、counts(度数)とmids(階級値)を使えばOKです↓

h1 <- hist(x)
h1$mids[which.max(h1$counts)]


[1] 45

階級の取り方を指定する場合↓

h2 <- hist(x, breaks=seq(25, 85, 10))
h2$mids[which.max(h2$counts)]


[1] 50

階級の取り方が適切かどうかは目で見て判断しなきゃいけないので、hist関数を実行した際に表示される描画結果を見てチェックするという必要はありそうです。

コメント

このブログの人気の投稿

Rのグラフで軸の目盛りの刻み幅を変更する方法

Rで繰り返しを含む数列の生成(rep関数、seq関数)

reorderを使ってggplotの棒グラフの並び順を降順にする方法