kivantium活動日記

プログラムを使っていろいろやります

声優で学ぶ統計学

オタクもすなる統計といふものを、非オタもしてみむとてするなり。

アニメ顔認識の関連研究を調べていたら驚異のアニヲタ社会復帰への道というブログを発見し、コンテンツの奥深さに大変感動を受けました。作者の@Med_KUさんは声優統計というサークルの同人誌にも寄稿されているらしく、この同人誌もまた素晴らしい内容を扱っていました。

というわけで今回は声優について統計で何かやろうと思います。

Rのインストール

統計を扱う上で便利なRという言語を使ってみます。Ubuntuなら

sudo apt-get install R-base-core

でOKです。

声優の身長分布を調べる

声優の身長(と体重) 身長順(女性)から身長のデータを持ってきてCSVで保存しました。

1列目には声優の名前、2列目には声優の身長(cm単位、四捨五入して整数に加工済み)を入れます。
また、1行目では変数名を指定するのでそれぞれ、name, heightと入れてあります。ファイル名はvoice.csvにしました。

ではまずCSVファイルを読み込んでみましょう。インストールしていれば"R"というコマンドでプロンプトが起動します。

$ R
> data <- read.csv("voice.csv")
> data
         name   height
1 葛城  七穂    173
2 日下  ちひろ  173
3 本田  貴子    173
4 雨蘭  咲木子  173
5 川島  千代子  172
6 中田  あすみ  172
7 光明寺  敬子  172
8 石井  翔子    170
9 小島  幸子    170
    (中略)
630 志村  由美  139

このように、read.csvというコマンドを使うことでCSVファイルを読み込むことができます。

次に読み込んだデータを解析してみます。データの特徴を表す量として代表的なのは平均と標準偏差です。
平均はその分布の中で代表的な値を、標準偏差はデータのばらつきを表します。
数式で書くと、


です。

Rで平均と標準偏差を求めるには、

> mean(data$height)
[1] 157.0381
> sd(data$height)
[1] 5.637864

のようにします。data$height は、dataのうちheightの値だけを使うことを表す記法です。

これで平均と標準偏差が分かったわけですが、統計学には「平均的な人間は1つのおっぱいと1つの精巣を備える」という名言があるように、平均だけ知って満足するととんでもない誤解につながることがあります。それを防ぐには分布を眺めるのが効果的です。分布を眺める方法として一番簡単なのはヒストグラムを使うことです。

> hist(data$height, breaks=seq(135,175,1))

breaks=seq(135,175,1)は、135から175までを1刻みで表示するというオプションです。この結果がこちら。
f:id:kivantium:20141212173224p:plain:w500
160cmあたりが最も多く、そこから離れるに従ってだんだん減っていくという分かりやすい分布をしていることが見て取れます。

さて、このようにヒストグラムを眺めることで分布の特徴が分かるわけですが、分布のなかでも数学的に取り扱いやすい分布というものがいくつかあります。その中で一番重要なものが正規分布です。正規分布を式で書くと、

となり、μとσに応じてこのような形をとります。(Wikipediaより引用)
f:id:kivantium:20141212174000p:plain:w500

この分布が重要になる理由の一つに中心極限定理の存在があります。これはもともとの分布がどのような分布であっても、そこからいくつかサンプルを取り出して平均を取った時、その平均(標本平均)はサンプル数が十分大きければ正規分布で近似できるというものです。

ここではこの声優の身長データを用いて中心極限定理を実感してみようと思います。ヒストグラムを見れば分かるように声優の身長分布は左右非対称で正規分布っぽくありません。そこでいくつかの大きさのサンプルを取り出してその平均の分布を調べてみることにします。

まずはじめに、正規分布ヒストグラムを見てみます。
Rで正規分布に従う乱数を生成するにはrnormという関数を使います。

> norm <- rnorm(10000, mean=mean(data$height), sd=sd(data$height))
> hist(norm, xlim=c(135,175), breaks=41)

histでは、135-175の範囲を41分割して表示しています。結果がこちら
f:id:kivantium:20141212233702p:plain:w500
10000個のサンプル数ではこんなもんでしょう。

では、標本平均の分布を調べてみます。
Rで標本をとるにはsample関数を使います。ここではサンプル数5の標本をとって標本平均の分布を調べます。
中心極限定理によれば、標本平均の分布は平均が母集団の平均標準偏差が母集団の標準偏差で割ったに近づきます。そこで、近似する先の正規分布も同時に表示してみます。度数分布は割合を表すようにfreq=FALSEというオプションをつけます。

> mean <- vector(length=10000)
> for(i in 1:10000){
+ mean[i] <- mean(sample(data$height, 5))
+ }
> hist(mean, breaks=seq(135,175,1))
> x <- seq(135, 175, by=0.01)
> curve(dnorm(x,mean=mean(data$height),sd=sd(data$height)/sqrt(5)),col="red",add=TRUE)

f:id:kivantium:20141213001209p:plain:w500

かなりきれいな分布が出ました。

(はまったポイント:histでfreqの指定を行わないとcurveが上書きされないっぽいです。原因は調べていません。)

上の定理によればサンプルサイズを大きくすると標本平均の分散は小さくなります。N=20,N=100での結果がこちらです。
f:id:kivantium:20141213002228p:plain:w300 f:id:kivantium:20141213001730p:plain:w300
というわけでNが大きくなるにつれて分散が小さくなっていく様子が見て分かります。
Nを大きくすると平均のばらつきが小さくなるのが、実験で多くのデータを使うとより正確な値が得られる理由の一つです。

Rの入門ということで声優が全く関係なくなってしまいましたが、今後声優要素を絡めた分析を行いたいと思います。