t検定は、母分散が未知のときに母平均に関する仮説を検定する手法で、実用上最も広く使われている検定のひとつです。z検定が母分散既知を前提とするのに対し、t検定は標本から推定した分散を使うため、現実のデータ分析に適しています。
t検定は1908年にウィリアム・ゴセット(ペンネーム: Student)がギネスビール醸造所の品質管理のために考案しました。小標本でも信頼性の高い推論ができるこの手法は、100年以上経った今でもデータ分析の基本ツールです。
本記事の内容
- t分布の定義と性質
- 1標本t検定の検定統計量の導出
- 対応のある2標本t検定
- 独立2標本t検定(等分散の場合とウェルチの場合)
- scipy.stats での実装
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
t分布とは
定義
$Z \sim N(0, 1)$ と $V \sim \chi^2_k$(自由度 $k$ のカイ二乗分布)が独立のとき、
$$ T = \frac{Z}{\sqrt{V / k}} $$
は 自由度 $k$ のt分布 $t_k$ に従います。
確率密度関数
$$ f(t) = \frac{\Gamma\left(\frac{k+1}{2}\right)}{\sqrt{k\pi}\,\Gamma\left(\frac{k}{2}\right)}\left(1 + \frac{t^2}{k}\right)^{-\frac{k+1}{2}} $$
ここで $\Gamma(\cdot)$ はガンマ関数です。
t分布の性質
- 平均 0 で左右対称
- 自由度が小さいほど裾が重い(標準正規分布より外れ値が出やすい)
- 自由度 $k \to \infty$ で標準正規分布 $N(0, 1)$ に収束
なぜz検定ではなくt検定が必要か
z検定の検定統計量は $Z = \frac{\bar{X} – \mu_0}{\sigma / \sqrt{n}}$ ですが、実際には母標準偏差 $\sigma$ は未知であり、標本標準偏差 $s$ で推定する必要があります。
$$ s = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(X_i – \bar{X})^2} $$
$\sigma$ を $s$ で置き換えたとき、検定統計量は
$$ T = \frac{\bar{X} – \mu_0}{s / \sqrt{n}} $$
となりますが、$s$ は確率変数であり、$T$ は標準正規分布には従いません。$T$ が従う分布を導出しましょう。
t分布に従うことの導出
$H_0: \mu = \mu_0$ のもとで $X_i \sim N(\mu_0, \sigma^2)$ です。
$$ Z = \frac{\bar{X} – \mu_0}{\sigma / \sqrt{n}} \sim N(0, 1) $$
また、
$$ \frac{(n-1)s^2}{\sigma^2} = \sum_{i=1}^{n}\left(\frac{X_i – \bar{X}}{\sigma}\right)^2 \sim \chi^2_{n-1} $$
が成り立ちます。正規母集団において $\bar{X}$ と $s^2$ は独立であることが知られています。
$T$ を変形します。
$$ \begin{align} T &= \frac{\bar{X} – \mu_0}{s / \sqrt{n}} \\ &= \frac{(\bar{X} – \mu_0) / (\sigma / \sqrt{n})}{s / \sigma} \\ &= \frac{Z}{\sqrt{s^2 / \sigma^2}} \\ &= \frac{Z}{\sqrt{\chi^2_{n-1} / (n-1)}} \end{align} $$
これはまさにt分布の定義の形であり、$T \sim t_{n-1}$ です。
1標本t検定
問題設定
母集団 $X \sim N(\mu, \sigma^2)$($\sigma^2$ 未知)から $n$ 個の標本を抽出します。
$$ H_0: \mu = \mu_0, \quad H_1: \mu \neq \mu_0 $$
検定統計量
$$ T = \frac{\bar{X} – \mu_0}{s / \sqrt{n}} \sim t_{n-1} \quad (\text{$H_0$ のもと}) $$
棄却域(両側検定)
$$ |T| > t_{\alpha/2, n-1} $$
ここで $t_{\alpha/2, n-1}$ は自由度 $n-1$ のt分布の上側 $\alpha/2$ 点です。
p値
$$ p = 2P(T_{n-1} \geq |t_{\text{obs}}|) $$
対応のある2標本t検定
問題設定
同一の被験者に対して処理前後の測定を行い、処理の効果を検定します。$n$ 組のペアデータ $(X_i, Y_i)$ に対し、差 $D_i = X_i – Y_i$ を計算します。
$$ H_0: \mu_D = 0, \quad H_1: \mu_D \neq 0 $$
検定統計量
差の標本平均 $\bar{D}$ と標本標準偏差 $s_D$ を用いて、
$$ T = \frac{\bar{D}}{s_D / \sqrt{n}} \sim t_{n-1} \quad (\text{$H_0$ のもと}) $$
これは差 $D_i$ に対する1標本t検定と同じ形です。
なぜ対応を考慮するのか
対応のあるデータでは、個体差の影響が差 $D_i$ を取ることで相殺されます。たとえば薬の効果を調べるとき、被験者ごとの体重の違いなどの個人差は $D_i = X_i – Y_i$ を取ることで除去されるため、検出力が向上します。
独立2標本t検定
問題設定
2つの独立な母集団からの標本を比較します。
$$ X_1, \dots, X_{n_1} \sim N(\mu_1, \sigma_1^2), \quad Y_1, \dots, Y_{n_2} \sim N(\mu_2, \sigma_2^2) $$
$$ H_0: \mu_1 = \mu_2, \quad H_1: \mu_1 \neq \mu_2 $$
等分散の場合(Studentのt検定)
$\sigma_1^2 = \sigma_2^2 = \sigma^2$ を仮定するとき、共通の分散をプールした分散で推定します。
$$ s_p^2 = \frac{(n_1 – 1)s_1^2 + (n_2 – 1)s_2^2}{n_1 + n_2 – 2} $$
ここで $s_1^2, s_2^2$ はそれぞれの群の標本分散です。
検定統計量は次のようになります。
$$ T = \frac{\bar{X} – \bar{Y}}{s_p\sqrt{\dfrac{1}{n_1} + \dfrac{1}{n_2}}} \sim t_{n_1 + n_2 – 2} $$
導出
$H_0$ のもとで $\bar{X} – \bar{Y} \sim N(0, \sigma^2(1/n_1 + 1/n_2))$ です。
$\sigma^2$ を $s_p^2$ で推定すると、z検定の統計量の $\sigma$ を $s_p$ に置き換えた形になり、
$$ T = \frac{(\bar{X} – \bar{Y}) / \sqrt{\sigma^2(1/n_1 + 1/n_2)}}{s_p / \sigma} = \frac{Z}{\sqrt{\chi^2_{n_1+n_2-2}/(n_1+n_2-2)}} $$
$Z$ と $\chi^2$ が独立であることから $T \sim t_{n_1+n_2-2}$ が得られます。
等分散でない場合(ウェルチのt検定)
$\sigma_1^2 \neq \sigma_2^2$ の場合、ウェルチのt検定(Welch’s t-test) を使います。
$$ T = \frac{\bar{X} – \bar{Y}}{\sqrt{\dfrac{s_1^2}{n_1} + \dfrac{s_2^2}{n_2}}} $$
自由度は ウェルチ-サタスウェイトの近似 で求めます。
$$ \nu = \frac{\left(\dfrac{s_1^2}{n_1} + \dfrac{s_2^2}{n_2}\right)^2}{\dfrac{(s_1^2/n_1)^2}{n_1 – 1} + \dfrac{(s_2^2/n_2)^2}{n_2 – 1}} $$
この $\nu$ は一般に整数にならないため、近い値に丸めるか、連続的な自由度として扱います。
ウェルチのt検定は等分散を仮定しないため、等分散かどうか不明な場合は常にウェルチのt検定を使うのが安全です。
Pythonでの実装
1標本t検定
import numpy as np
from scipy import stats
# データ: ある学校の生徒30人のテスト点数
np.random.seed(42)
scores = np.random.normal(72, 10, 30)
# 帰無仮説: 母平均は70点
mu_0 = 70
# 1標本t検定
t_stat, p_value = stats.ttest_1samp(scores, mu_0)
print("=== 1標本t検定 ===")
print(f"標本サイズ: n = {len(scores)}")
print(f"標本平均: {np.mean(scores):.4f}")
print(f"標本標準偏差: {np.std(scores, ddof=1):.4f}")
print(f"検定統計量: t = {t_stat:.4f}")
print(f"p値 (両側): {p_value:.4f}")
print(f"α = 0.05 での判定: {'棄却' if p_value < 0.05 else '棄却しない'}")
対応のあるt検定
import numpy as np
from scipy import stats
# データ: 10人の被験者のダイエット前後の体重
np.random.seed(42)
before = np.random.normal(70, 8, 10)
after = before - np.random.normal(2, 3, 10) # 平均2kg減少
# 対応のあるt検定
t_stat, p_value = stats.ttest_rel(before, after)
print("=== 対応のある2標本t検定 ===")
print(f"被験者数: n = {len(before)}")
print(f"前: 平均 = {np.mean(before):.2f} kg")
print(f"後: 平均 = {np.mean(after):.2f} kg")
print(f"差の平均: {np.mean(before - after):.2f} kg")
print(f"検定統計量: t = {t_stat:.4f}")
print(f"p値 (両側): {p_value:.4f}")
print(f"α = 0.05 での判定: {'棄却' if p_value < 0.05 else '棄却しない'}")
独立2標本t検定(ウェルチ)
import numpy as np
from scipy import stats
# データ: 2つの教授法でのテスト点数
np.random.seed(42)
method_a = np.random.normal(75, 10, 25)
method_b = np.random.normal(70, 12, 30)
# ウェルチのt検定(equal_var=False)
t_stat, p_value = stats.ttest_ind(method_a, method_b, equal_var=False)
print("=== 独立2標本t検定(ウェルチ)===")
print(f"群A: n={len(method_a)}, 平均={np.mean(method_a):.2f}, SD={np.std(method_a, ddof=1):.2f}")
print(f"群B: n={len(method_b)}, 平均={np.mean(method_b):.2f}, SD={np.std(method_b, ddof=1):.2f}")
print(f"検定統計量: t = {t_stat:.4f}")
print(f"p値 (両側): {p_value:.4f}")
print(f"α = 0.05 での判定: {'棄却' if p_value < 0.05 else '棄却しない'}")
# 等分散を仮定した場合との比較
t_stat_eq, p_value_eq = stats.ttest_ind(method_a, method_b, equal_var=True)
print(f"\n--- 参考: 等分散仮定 (Student) ---")
print(f"検定統計量: t = {t_stat_eq:.4f}")
print(f"p値 (両側): {p_value_eq:.4f}")
t分布とz検定の比較を可視化
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
x = np.linspace(-5, 5, 1000)
fig, ax = plt.subplots(figsize=(10, 6))
# 標準正規分布
ax.plot(x, stats.norm.pdf(x), 'k-', linewidth=2.5, label='$N(0, 1)$')
# 各自由度のt分布
for df, color in zip([2, 5, 10, 30], ['red', 'orange', 'green', 'blue']):
ax.plot(x, stats.t.pdf(x, df), color=color, linewidth=1.5,
linestyle='--', label=f'$t_{{{df}}}$')
ax.set_xlabel('$t$', fontsize=13)
ax.set_ylabel('Probability Density', fontsize=13)
ax.set_title('t-distribution vs Standard Normal Distribution', fontsize=14)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
ax.set_ylim(bottom=0)
plt.tight_layout()
plt.show()
3種類のt検定の使い分けフローチャート
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# シミュレーション: 3種類のt検定の検出力比較
np.random.seed(42)
n_sim = 5000
alpha = 0.05
# 真の効果がある状況
mu1, mu2 = 5.0, 4.0
sigma = 2.0
n = 15
reject_paired = 0
reject_ind = 0
for _ in range(n_sim):
# 対応のあるデータ(個体差あり)
subject_effect = np.random.normal(0, 5, n)
x_paired = mu1 + subject_effect + np.random.normal(0, sigma, n)
y_paired = mu2 + subject_effect + np.random.normal(0, sigma, n)
# 対応のあるt検定
_, p_paired = stats.ttest_rel(x_paired, y_paired)
if p_paired < alpha:
reject_paired += 1
# 独立2標本t検定(対応を無視)
_, p_ind = stats.ttest_ind(x_paired, y_paired, equal_var=True)
if p_ind < alpha:
reject_ind += 1
power_paired = reject_paired / n_sim
power_ind = reject_ind / n_sim
fig, ax = plt.subplots(figsize=(8, 5))
bars = ax.bar(['Paired t-test', 'Independent t-test'],
[power_paired, power_ind],
color=['steelblue', 'coral'], edgecolor='black')
ax.axhline(y=0.80, color='gray', linestyle='--', linewidth=1.5,
label='Target power = 0.80')
ax.set_ylabel('Power ($1 - \\beta$)', fontsize=13)
ax.set_title('Paired vs Independent t-test: Power Comparison', fontsize=14)
ax.legend(fontsize=11)
ax.set_ylim(0, 1)
ax.grid(True, alpha=0.3, axis='y')
for bar, val in zip(bars, [power_paired, power_ind]):
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.02,
f'{val:.3f}', ha='center', fontsize=12, fontweight='bold')
plt.tight_layout()
plt.show()
print(f"対応のあるt検定の検出力: {power_paired:.4f}")
print(f"独立2標本t検定の検出力: {power_ind:.4f}")
対応のあるデータに対して対応のあるt検定を使うと、個体差を除去できるため検出力が大幅に向上します。
まとめ
本記事では、t検定の理論と実装について解説しました。
- t分布: $T = Z / \sqrt{\chi^2_k / k}$ で定義。自由度が小さいほど裾が重く、$k \to \infty$ で正規分布に収束
- 1標本t検定: $T = \frac{\bar{X} – \mu_0}{s / \sqrt{n}} \sim t_{n-1}$。母分散未知で母平均を検定
- 対応のあるt検定: 差 $D_i$ に対する1標本t検定。個体差を除去して検出力を向上
- 独立2標本t検定: 等分散なら $t_{n_1+n_2-2}$、等分散でなければウェルチの近似自由度を使用
- 実用上のポイント: 等分散かどうか不明なときはウェルチのt検定が安全
次のステップとして、以下の記事も参考にしてください。