等分散性(分散の同一性)の検定を流れで見ていく


検定において、「別々の母集団の母分散が等しいか?」ということが意外と必要だったりします
(ちなみに、自分は日常で分散の同一性が必要な場面にはまだ出会ってないですが。。)

統計検定にも時たま出てくるので、アウトプットの意味合いもこめて順に解説していきます。

前置き(時間ない方は読み飛ばしても問題ありません)

例えば、平均の差の検定(分散分析)をする時の前提として「母集団の分散が等しい」と仮定していることがあります。
これは、すでに等分散性を確認して確かめているからそういうことが言える、という背景がありますので、知らないうちに使われていることが多いのかなと感じています(もちろん問題文とかに書いてないですw)。

実際の流れ

それぞれの仮説

まず、正規分布に従う母集団が二つ。(それぞれN($μ_1$, $σ_1$)、N($μ_2$, $σ_2$)とします)

ここで帰無仮説はもちろん「二つの分散が等しい」ことです
$$H_0: σ_1 = σ_2$$
対立仮説は差がある(どちらかが大きい)と考えます

このときに使うのはF分布となります(すぐに詳細は解説)

それぞれの統計量を確認

各母集団からm, n個ずつサンプルをとってきて、それぞれを
$x_{11}, x_{12}, ..., x_{1m}$
$x_{21}, x_{22}, ..., x_{2n}$
とします。

平均は
$\bar{x_1} = \frac{1}{m}\sum_{i=1}^{m}x_{1i}$
$\bar{x_2} = \frac{1}{n}\sum_{i=1}^{n}x_{2i}$

ここで、以前$χ^2$について考えます
($χ^2$は分散が特定の分散と等しいか?とか、独立しているか?などを検定するときによく用いられます)

それぞれ

$$ χ_1^2 = \sum(\frac{x_i - \bar{x_i}}{σ_1})^2 $$

$$ χ_1^2 = \sum(\frac{x_i - \bar{x_i}}{σ_2})^2 $$

($\sum$はそれぞれ$\sum_{i=1}^{m}$, $\sum_{i=1}^{n}$です。なんかlatex調子よくなかったので別にしました。。)

検定

この$χ_1^2$、$χ_2^2$ はそれぞれm-1, n-1の自由度に従って分布しています(詳細は以前書いた記事を参考に!)

これをそれぞれの自由度で割ったもの(F値)がF(m-1, n-1)の分布に従います。

$$ \hat{m} = {\frac{1}{m-1} \sum_{i=1}^{m}\frac{(x_i - μ)^2}{σ_1^2}}$$

$$ \hat{n} = {\frac{1}{n-1} \sum_{i=1}^{n}\frac{(x_i - μ)^2}{σ_2^2}}$$

$$F = \frac{\hat{m}}{\hat{n}}$$

ここで、そもそもの帰無仮説を思い出すと、「分散は等しい」ということでしたので、「$σ_1^2 = σ_2^2$」となるので、

$$F = \frac{{\frac{1}{m-1} \sum_{i=1}^{m}(x_i - μ)^2}}{{\frac{1}{n-1} \sum_{i=1}^{n}(x_i - μ)^2}}$$

(ちなみに、常に分子>分母になるようにします)

これ、単に最終的に不偏分散の比をとっているだけなんですよねw
つまり、それぞれの不偏分散を$s_1^2, s_2^2$とすると
$$F = \frac{s_1^2}{s_2^2}$$
ですw
ここで算出した値があらかじめ用意されているF分布の表であったり、プログラミングで検出してくれたりして、棄却できるか判断します。

遠回りした感もありますが、問題を解くときや仕事で使う際は直接不偏分散で割って求めるので良きです。

PythonでF分布を見ていく

せっかくなので、pythonで使えないと!ということからF分布を見てみましょう

import numpy as np
import matplotlib.pyplot as plt

from scipy import stats

x = np.linspace(-2, 5, 120)
plt.figure(figsize=(15, 8))
for dfn in range(1, 20, 5): # dfn: degree of freedom numerator(分子),
  for dfd in range(1, 20, 5): # dfd: degree of freedom denominator(分母),
    y = stats.f.pdf(x, dfn=dfn, dfd=dfd)
    plt.plot(x, y, label=f'dfn:{dfn}, dfd: {dfd}')

plt.legend()
plt.show()

F分布を描画するということはほぼないと思いますが、自由度が大きくなるにつれて尖度があがっています

F検定

では、F検定をして締めくくります

適宜コメントをつけていますが、さっくりとコードだけ書いて締めくくります

import pandas as pd

# データ準備
rng = np.random.default_rng(seed=123)
A = rng.integers(70, 100, (8,))
B = rng.integers(50, 100, (12, ))
A = pd.DataFrame({'A': A})
B = pd.DataFrame({'B': B})

# 直接確認したい時はコメントアウト外してくださいませ!
# display(A, B)

# 統計量の確認
sample_sizeA = len(A) # 標本サイズ
sample_sizeB = len(B)

varA = np.float(A.var(ddof=1)) # 不偏分散
varB = np.float(B.var(ddof=1))

# 検定
def F_test(size1, size2, var1, var2):

  # size1>size2, varも同様
  dfn= size1 - 1
  dfd = size2 - 1
  f = var1/var2
  print(f'F値: {f}')

  # 1 - 累積分布関数で棄却域を算出
  p = 1 - stats.f.cdf(f, dfn=dfn, dfd=dfd)
  print(f'棄却域: {p}')

  if p > 0.05:
    print('棄却できません!')
  else:
    print('棄却されました!')


if varA > varB:
  F_test(sample_sizeA, sample_sizeB, varA, varB)
else:
  F_test(sample_sizeB, sample_sizeA, varB, varA)

今回の用意したサンプルでは有意水準5%の領域ではp=0.17となり、0.05< 0.17より棄却されず、分散には差がある!という結論になりました!
他にもいろんなデータでぜひ確認してみると面白いかもです!

今回参考にさせていただいた記事

基本統計学
28-3. 等分散性の検定
2018年6月統計検定2級の問題の解説(その3)