平均、分散、標準偏差をPythonで求める

統計

標本を度数分布表に落とし込み、ヒストグラムで描画することで大まかな傾向が見えてきます。

次に、より細かな分析を行うために度数分布表の特色を数値で見ることにしましょう。

そこで、一般的に用いられるのが「平均」「分散」「標準偏差」ですね。

ということで、この三つはどんな意味があるかを説明して、さらにPython を使って、実際に計算してみましょう。

平均値とは何?

平均値は一般的に、収集されたデータの代表値として使われます。

集めたデータが100あったとして、そのすべてのデータを一つ一つ見て、特徴をとらえようとするよりも、そのデータの平均値を見たほうが、データの全体像をつかみやすいです。

平均値と同じように扱われる値としてあるのが期待値で「未来に適用できる平均値」という扱いになります。

例えば、川で魚を10匹釣ったとしてその平均値が5センチとすると、次に釣れる魚の大きさも約5センチくらいということが、予測できます。

平均値の数式の解説

平均値の求め方は皆さんわかっていると思いますが、その数式は以下のようになります。

数式に出てくる記号を一つ一つ説明してみましょう。

まず の意味は標本の平均値であり母集団の平均はで表されます。

はデータの個数、各データは  で表し、 の右下の が何番目なのかを表します。

例えば、 3, 5, 4, 1, 7 というデータがあったとしします。

普通に平均値を計算すれば、以下のように計算できます。

これを数式に当てはめてみると、データ個数  になります。

そして、, …  ですね。

なので、

と表せます。

ここではデータ個数が5個しかないので一つずつ足すことができますが、データの数が1万など膨大な数の場合、いちいち1万回足すという記述ができないので記号 を使います。

この意味はエクセルなどでもおなじみの、合計するという意味ですね。

例えば1番目の値から 番目の値を足す際には以下の式で表しす。

これを で割ると、以下の式のように平均が求められるというわけです。

 の使い方

この の使い方ですが、上下の数値を変えることで、足し算の範囲を設定できます。

 の場合、1番目から5番目の値を足す場合は、以下のように  、 として、

2番目から4番目を値を足す場合は、

3番目から最後までの値を足す場合は、

となります。

Python で平均値を求める

Pythonを使って数値3, 5, 4, 1, 7 の平均値を求めてみましょう。

import numpy as np # 数値計算ライブラリ numpyをインポート
average = np.array([3,5,4,1,7]) # array にデータを格納
average 
array([3, 5, 4, 1, 7])

データの合計値を求める。

np.sum(average) # 合計値を求める関数
20

データの数を数える。

len(average) # データの数を数えるlen()関数
5

平均値を求めるプログラムを書く。

N = len(average) # データの個数を定義
sum_average = np.sum(average) # データの合計値を求める
mean = sum_average/N # データの合計をデータの個数で割る
mean
4.00

実はこんな面倒なプログラムを書かなくても、np.mean()で平均が求められます。

np.mean(average) # 平均値を求めるプログラム 
4.00

簡単ですね。

分散とは何?

分散とはデータが平均値とどれだけ離れているか、データの散らばり具合を示す値です。

文で説明してもわかりにくいので、とりあえず例を見てみましょう。

二つのヒストグラムがありますが、青いヒストグラムはすべてのデータがより平均値に近くなっています。

つまり青いヒストグラムの平均値は、このデータ全体をよく表していることになりますね。

反対に赤いヒストグラムは、なだらかな線で左右に広がっていのがわかります。

両端が平均値から離れているため、平均値がこのデータを代表しているとはいいがたいですね。

データが、平均値からどれだけ散らばっているかを示す値が分散というわけです。

分散の数式は以下の通り。

この式を簡単に説明すると、分散は「データの各値と、その平均との差を2乗した値の平均」となります。

つまり、 がデータの値であり、そこから平均  を引きその答えを2乗。

それをデータ数 で割った値が分散になります。

分散を求めてみる

では実際に、分散を求めてみましょう。

Pythonで分散を求めるコードをまとめると、以下のようになります。

分散を求めるためのデータは、平均値を求めるために使ったデータ(average)をもとにしています。

実装してみましょう。

average_sigma2 = np.sum((average-mean)**2)/N
average_sigma2
4.0

分散は 4.0 と求められました。

一行ずつ解説していきます。

まず array に格納されている、データの確認をしてみましょう。

average 
array([3, 5, 4, 1, 7])

次にarray から、1データごとに平均値を引いていきます。

平均値はaverage (4.0) を使っています。

average - mean 
array([-1.,  1.,  0., -3.,  3.])

つぎに、平均値を引いた値を二乗します。

(average - mean)**2  
array([1., 1., 0., 9., 9.])

二乗した値をすべて足していきます。

np.sum((average - mean)**2)  
20.0

それをデータの個数Nで割った商が分散になります。

np.sum((average - mean)**2)/N  
4.0

ちなみに分散を求める関数があるので、通常はこれを使います。

np.var(average, ddof=0)  
4.0

分散は4.0と求められました。

標本分散と不偏分散

分散には標本分散と不偏分散があり、上記の実装で求めた値は標本分散になります。

統計的に重要な概念なので説明します。

本当に正確な値を見つけたいのであれば、母集団すべての値を計算すればいいのですが、それは現実的に不可能なので、母集団から標本を抽出するわけです。

その抽出した標本の分散が標本分散です。

しかし標本の分散はあくまでも標本の分散であり、母集団の分散とは違う可能性があります。

そこで、標本に存在しているかもしれない偏りを補正した分散が不偏(偏りがない)分散です。

不偏分散の数式を紹介しておきますね。

標本分散と比べて、分母が  と小さくなります。

これをPythonのコードで書くと、

np.var(average, ddof=1)
5.0

不偏分散は5.0になります。

ここで、「ddof」が1と 0 の違いは何か気になりますよね。

ちなみにこの「ddof」は何かというと「Delta Degrees Of Freedom」で「デルタ自由度」と訳されます。

ちなみに数式の中で使われているのが「」の部分。

自由度がどういう意味かなんですが、すごく簡単に説明すると「自由に決めることができる値の数」です。

余計分けわかりませんよね。

例を使って説明します。

分散を求めるために使った「3, 5, 4, 1, 7」という5つのデータをすべて足すと

3+5+4+1+7 = 20

答えは20になります。

では次に答えが20になるような値を自由に決めてみます。

例として

3+5+4+1+7 = 20

使うと、最後の数字は7でなければ、20は成り立ちません。

つまり前の4つ数字は自由に決められますが、最後の数字は自由に決めることができないですよね。

お分かりでしょうか?

つまり「」は総データ数から1引いた数までは自由に決められるという意味です。

これをPython で表すと、「ddof = 1」となるわけです。

そしてこのデータセットの標本分散は「4.0」不偏分散は「5.0」になります。

標準偏差

標準偏差も分散と同じく、データのバラつき見るために用いられる値です。

分散という値があるのになぜ標準偏差を使う理由は、現実に当てはめて理解しやすい値が算出できるからです。

というのも、標準偏差は分散の平方根、逆に言うと標準偏差を二乗すれば分散になる。

例を挙げると、小学生の算数テストの標準偏差が10点だったとすると、分散は100点になってしまいます。

ちょっと理解に苦しみますよね。

分散は、統計的には正解でも現実的に受け入れるのが難しい場合があるので、通常は標準偏差を使って散らばりを表します。

ちなみに、標準偏差の公式は以下になります。

ちなみにこの公式では、データ数から1を引いていないので、標本標準偏差になります。

データ数を自由度1にした不偏標準偏差の公式が以下になります。

では実際にまず、標本標準偏差をpythonで実装してみましょう。

今回も分散で使ったデータを使います。

average_sigma2 = np.sum((average-mean)**2)/N 
average_sigma2 
4.0

以上の計算で、分散は4.0と求められました。

標準偏差は分散の平方根なので、以下のように書きます

average_sigma2 = np.sum((average - mean)**2)/N
average_sigma = np.sqrt(average_sigma2)
average_sigma 
2.0

手計算ではこうなりますが、標準偏差の関数「.std()」を使うことで、1行で書くことができます。

np.std(average, ddof = 0)
2.0

ddof つまりデルタの自由度が0なので、標本標準偏差ということがわかりますね。

不偏標準偏差を求める場合は、ddof = 1 とすることで、求められます。

np.std(average, ddof = 1)
2.23606797749979

標本標準偏差の範囲と比べて、不偏標準偏差の散らばりが多少大きいのが分かりますね。

コメント

タイトルとURLをコピーしました