スチューデントのt検定(概要とpython実装)

スチューデントのt検定について

  • 2群間の平均値の差を比較する検定
  • 2群間の平均値が独立であり(データに対応がない)、かつ2群間に等分散性が仮定できる場合に用いる(下記図参照)


コード

  • 2群間には対応はなくそれぞれ正規分布しており、等分散であること分かっているとして t検定を実施する。
  • 有意水準を0.05,帰無仮説を「2群間の平均値に差がないこと」とする。
import numpy as np
from scipy import stats
import seaborn as sns

#用いるデータ
A = np.array([6.3, 8.1, 9.4, 10.4, 8.6, 10.5, 10.2, 10.5, 10.0, 8.8])
B = np.array([4.8, 2.1, 5.1, 2.0, 4.0, 1.0, 3.4, 2.7, 5.1, 1.4, 1.6])

#試しにバイオリンプロットを作成
sns.violinplot(x=['A' for i in range(len(A))]+['B' for i in range(len(B))],
y=np.concatenate([A, B]))

#t検定を実施
result = stats.ttest_ind(A, B)
print('p-value:',result.pvalue)
# >>> p-value: 6.698194360479442e-09

p < 0.05なので、帰無仮説は棄却され、2群の代表値には差があるといえる。

バイオリンプロットはこんな感じ。


検定の手順(詳細)

手順

はじめに...
二つの標本が正規分布しており、等分散していることを確認しておく。

  1. 仮説の設定
    帰無仮説(Ho):「2群間に差がない」と仮定する。
    対立仮説(H1):「2群間に差がある」と仮定する。
  2. 有意水準をαを設定する。
  3. 両群の「平均値$X$, 分散$S^2$」を求める。
  4. $S$ と $t$値を下式から求める。
  5. この時の自由度$df$は [$n_1 + n_2 - 2 $] の$t$分布に従うので、自由度 $df$ を求めたら $t$ 分布表から $t_a$ を求めて、計算した $t$ 値と比較する。
    $|t| \leqq t_a$ の時:帰無仮説は棄却できない。
    $|t| > t_a$ の時:帰無仮説を棄却する(有意差あり)

t値とSの算出式

$$ S = \sqrt{\frac{s_1^2(n_1-1)+s_2^2(n_2-1)}{n_1+n_2-2}} $$

$$ t = \frac{\bar{X_1}-\bar{X_2}}{S\sqrt{\frac{1}{n_1}+\frac{1}{n_1}}} $$

コード

#用いるデータ
A = np.array([49, 40, 52, 37, 55, 38, 45])
B = np.array([60, 52, 68, 55, 65, 47, 45, 62, 53])
#データ数
n1 = len(A)
n2 = len(B)
#平均値
X1 = A.mean()
X2 = B.mean()
#分散S^2
s1 = A.var()
s2 = B.var()
print('データ数)A:{}, B:{}'.format(n1,n2))
print('平均値)A:{}, B:{}'.format(round(X1,3),round(X2,3)))
print('分散)A:{}, B:{}'.format(round(s1,3),round(s2,3)))
#合成した分散値Sを求める。
S = np.sqrt((s1 * (n1-1) + s2 * (n2-1)) / (n1+n2-2))
print('S:', round(S,3))
#t値を算出する
t = (X1-X2) / (S * np.sqrt((1/n1)+(1/n2)))
print('t:',round(t,3))
#自由度df
df = n1 + n2 - 2
print('自由度:',round(df,3))
"""output
データ数)A:7, B:9
平均値)A:45.143, B:56.333
分散)A:43.265, B:56.0
S: 7.109
t: -3.123
自由度: 14
"""

このとき、自由度 $df=14$ の t 分布に従うので、t 分布表より t0.05 = 2.145 であることが分かる。
計算した t値=3.124 なので、$|t| > t_a$ となり、帰無仮説を棄却し対立仮説を採用する。(有意差があり)

参考