母集団の分散を推定します。
これには分散ではなく、不偏分散を使います。
データは正規分布であるとします。
データ数は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
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
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_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 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
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))
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))