不偏分散 | python3Xのブログ

python3Xのブログ

ここでは40代、50代の方が日々の生活で役に立つ情報や私の趣味であるプログラム、Excelや科学に関する内容で投稿する予定です。

母集団の分散を推定します。

これには分散ではなく、不偏分散を使います。

データは正規分布であるとします。

データ数は20,000

サンプリング数は30

仮にある区域の複数の中学校の男子生徒の身長ということにします。

全体の身長の平均と不偏分散を求めた後に

サンプリングして部分抽出を行い、それらの平均と不偏分散を求めます。

最後に、それらのデータの平均を求め

母集団の推定が合っていたかを確認します。

※不偏分散の値は毎回少し変動があります。

 

母集団の平均身長 = 159.98, 母集団の分散 = 36.1007
標本平均 = 159.166, 不偏分散 = 27.0774
標本平均 = 160.742, 不偏分散 = 31.6825
標本平均 = 159.724, 不偏分散 = 39.336
標本平均 = 158.603, 不偏分散 = 41.4774
標本平均 = 159.25, 不偏分散 = 36.6598
標本平均 = 159.14, 不偏分散 = 36.0435
標本平均 = 159.305, 不偏分散 = 36.2201
標本平均 = 159.624, 不偏分散 = 46.2234
標本平均 = 159.89, 不偏分散 = 27.011
標本平均 = 161.919, 不偏分散 = 33.0734
無作為抽出全体の平均身長
159.736,  不偏分散の平均 = 35.4804

コード

import numpy as np
# 正規分布の乱数データ作成
def nrand():
    n = 0.0
    for _ in range(12):  # 0~11:12回のループ
        n += np.random.random() # random() : 0 ~1の乱数を発生
    return n - 6.0
# 平均身長:160 cm, 標準偏差:約6のデータを作成
def make_data(n):
    height = []  # 20000人分の身長データ
    for _ in range(n):
        height.append(160 + 6.0 * nrand())
    return height
# 平均と分散(variance:分散)
def mean_variance(height):
    n = len(height)
    m = float(sum(height)) / n  # 平均身長
    s1 = 0.0
    for x in height:
        a = x - m
        s1 += a * a    
    return m, s1 / n   # デー多数 n で割る  
# 平均と不偏分散
def mean_variance1(height):
    n = len(height)
    m = float(sum(height)) / n
    s1 = 0.0
    for x in height:
        a = x - m
        s1 += a * a
    return m, s1 / (n - 1) # デー多数 n から 1引いた値で割る
# 無作為抽出
def random_sampling(height, m):
    n = len(height)
    sample = []
    for i in range(n):
        if (n - i) * np.random.random() < m:
            sample.append(height[i])
            m -= 1
            if m <= 0: break
    return sample
# テスト
if __name__ == '__main__':
    np.random.seed(1)
    height = make_data(20000)
    print('母集団の平均身長 = %g, 母集団の分散 = %g' % mean_variance(height))
    m = 0.0
    v = 0.0
    for _ in range(10):
        a, b = mean_variance1(random_sampling(height, 30))
        m += a
        v += b
        print('標本平均 = %g, 不偏分散 = %g' % (a, b))
    print('無作為抽出全体の平均身長 %g,  不偏分散の平均 = %g' % (m / 10, v / 10))