Pythonで和、平均、中央値、最頻値、分散、標準偏差を計算する
Pythonを用いる際、和、平均、中央値、最頻値、分散、標準偏差が何を表し、どういう処理を行っているのか考えます。
環境
mac version10.10.5 OSX Yosemite
Python 3.6.1 |Anaconda 4.4.0 (x86_64)|
参考書籍
pythonからはじめる数学入門
完全独習 統計学入門
↑統計学がとてもわかりやすいのでおすすめです。
統計計算の関数
計算方法より、とにかく答えを知りたい、といった方はこちらを利用すれば一瞬です↓
{0:.2f}を使い少数点以下2桁まで表示させています。
from statistics import mean, median,variance,stdev
data = [100,200,300,400,500,500,600,700,800,800]
m = mean(data)
median = median(data)
variance = variance(data)
stdev = stdev(data)
print('平均: {0:.2f}'.format(m))
print('中央値: {0:.2f}'.format(median))
print('分散: {0:.2f}'.format(variance))
print('標準偏差: {0:.2f}'.format(stdev))
他にもnumpyを使うなどいろいろな方法があります。
Pythonの数値計算ライブラリ NumPy入門
以下、計算方法について詳しく見ていきます
平均
平均については
data = [800,200,700,300,100,400,500,500,600,800]
s = sum(data)
N = len(data)
mean = s / N
print('平均:{0:.2f}'.format(mean))
以上の計算式で求めることができます。
まずdataの配列にある数値を全てsum関数を用いて足し、len関数を使いdata配列にある数値の個数を数えます。
data配列の合計を個数で割れば平均となります。
中央値
中央値とは数の集まりの中央にある値のことです。つまり中央値では上から数えても下から数えても同じ順位になります。
中央値を求めたい数が奇数であれば、中央値は一つとなります。ですが数が偶数の場合は中央値は2つとなるので、その2数の平均値が中央値となります。
####例:
ある三人(Aさん,Bさん,Cさん)のテストの点数を表示します。Aさん80点、Bさん60点、Cさん100点であれば中央値は上から数えても下から数えても同じ順位となるAさん(80点)です。
ここにDさんが加わると(Dさん70点)、上から数えても下から数えても同じ順位となるのはAさんとDさんになるので中央値はAさんの80点とDさんの70点の平均点(80+70/2)である75点が中央値となります。
今回のdata配列では偶数個ですが、if文を使い奇数の場合でも求められるように条件分岐します。
また中央値を計算する際にはdata配列内のデータを昇順に並べかえる必要があるので、sort()メソッドを使い、配列内の数値を昇順に並び替えます。
data = [100,200,300,400,500,500,600,700,800,800]
N = len(data)
data.sort()
# 偶数の場合
if N % 2 == 0:
median1 = N/2
median2 = N/2 + 1
#pythonでは要素を0から数えるため-1します。
#また除算演算子は結果が整数でも小数点を返すので(6 / 3 = 3.0)int関数で整数にします
median1 = int(median1) - 1
median2 = int(median2) - 1
median = (data[median1] + data[median2]) / 2
print('データの中央値は:',median)
# 奇数の場合
else:
median = (N + 1) / 2
#pythonでは要素を0から数えるため-1します。
median = int(median) - 1
median = data[median]
print('データの中央値は:',median)
最頻値
最頻値とはもっとも多く出現している値のことです。次のような[1,1,1,1,2,2,3,4]配列では、1が4回出現しているため、1が最頻値となります。
まず一番多い要素を見つけるにはCounterクラスのmost_common()メソッドを使うと便利です。
>>> from collections import Counter
>>> list = [1,1,2,2,3,4,5,5,5]
>>> c = Counter(list)
>>> c.most_common()
[(1,2),(2,2),(3,1),(4,1),(5,3)]
#左から1が2回、2が2回、3が1回、4が1回、5が3回となります。
もっとも多い数が欲しい時は
>>> c.most_common(1)
と入力すると[(5, 3)]が表示されます。
また出現回数や最も多く出現した数のみ、算出したい場合は、
>>> mode = c.most_common(1)
>>> mode[0]
[(5,3)]
>>> mode[0][0]
5
>>> mode[0][1]
3
が表示されます。
今回はdata配列に複数の最頻値が見られるので、複数最頻値がある場合も考えます。
from collections import Counter
def calculate_mode(data):
c = Counter(data)
# すべての要素とその出現回数を取り出します。
freq_scores = c.most_common()
#c.most_common内の最も多い要素[0]の最大出現回数[1]を[0][1]で指定
max_count = freq_scores[0][1]
modes = []
#出現回数と最大出現回数が等しいかを確認します。
for num in freq_scores:
if num[1] == max_count:
modes.append(num[0])
return(modes)
if __name__ == '__main__':
data = [100,200,300,400,500,500,600,700,800,800]
modes = calculate_mode(data)
print('もっとも頻度の高い数は:')
for mode in modes:
print(mode)
分散と標準偏差
分散と標準偏差の理解には、平均と偏差といった考えが必要になりますので、合わせて解説します。
名前 | 数学(点数) |
---|---|
Aさん | 60 |
Bさん | 80 |
Cさん | 90 |
Dさん | 40 |
Eさん | 70 |
以上の5人の数学の点数をもとに以下、平均、偏差、分散、標準偏差を考えます。
求める値 | 計算式 |
---|---|
平均点 | 5人の数学の点数の合計 ÷ 人数 |
偏差 | 各個人の点数 - 平均点 |
分散 | 偏差の2乗の合計 ÷ 人数 |
標準偏差 | 分散の平方根(ルートの値) |
上記にある5人のテスト結果をもとにまずは平均点を表示します。 |
平均
(60+80+90+40+70) ÷ 5 = 68 が平均点となります。
5人の点数の合計をテストを受けた人数で割ります。
偏差
テストを受けた各個人の点数から平均点を引きます。
名前 | 計算式(点数-平均点) | 偏差 |
---|---|---|
Aさん | 60-68 | -8 |
Bさん | 80-68 | 12 |
Cさん | 90-68 | 22 |
Dさん | 40-68 | -28 |
Eさん | 70-68 | 2 |
以上の式で偏差を求めることができます。 | ||
また偏差の値は平均値からの差を表すので、偏差を全て足すと0になります。 |
分散
分散とはデータの散らばり具合を表すものです。平均から点数を引いた偏差を使えば、データの散らばり具合(分散)がわかりそうですが、偏差の値を全て足してしまうと、合計は必ず0になるため、偏差の値を2乗した平均値を分散の値とします。
*なぜ2乗するのか、より詳しい説明が欲しい方は下記ページを参考にするとわかりやすいです。
分散はなぜ2乗して求めるのか
名前 | 計算式 | -- |
---|---|---|
Aさん | -8² | 64 |
Bさん | 12² | 144 |
Cさん | 22² | 484 |
Dさん | -28² | 784 |
Eさん | 2² | 4 |
合計 | --- | 1480 |
分散 | 1480÷5 | 296 |
以上の5人の偏差の2乗の合計(1480) ÷ 人数(5人) = 296が分散の値となります。 |
標準偏差
分散の値は2乗していることから値が非常に大きくなります。このため分散の値を使うと、データの散らばりが分かりにくくなるので、分散の値の平方根を求めることで、見やすくします。この見やすくした値が標準偏差となります。
296の平方根は17.20,,,となるので、標準偏差は17.20,,,となります。
分散と標準偏差の値をpythonで求める式は、
def calculate_mean(data):
s = sum(data)
N = len(data)
mean =s/N
return mean
#平均からの偏差を求める
def find_difference(data):
mean = calculate_mean(data)
diff = []
for num in data:
diff.append(num-mean)
return diff
def calculate_variance(data):
diff = find_difference(data)
#差の2乗を求める
squared_diff = []
for d in diff:
squared_diff.append(d**2)
#分散を求める
sum_squared_diff = sum(squared_diff)
variance = sum_squared_diff/len(data)
return variance
if __name__ == '__main__':
data = [100,200,300,400,500,500,600,700,800,800]
variance = calculate_variance(data)
print('分散の値は:{0}'.format(variance))
std = variance**0.5
print('標準偏差は:{0}'.format(std))
以上になります。