🐕

サンプルサイズの決め方3章 1つの母平均の検定-母分散が既知の場合

2024/09/24に公開

はじめに

このブログ記事では、永田靖著『サンプルサイズの決め方』(朝倉書店)の3章を参考に、母平均の検定、検出力の計算方法、適切なサンプルサイズの設計方法について解説します。これらの概念は、実験計画やデータ分析において非常に重要です。これら統計学の基本的な概念をPythonを用いて実装しながら確認していきます。

母分散が既知の場合の母平均の検定

サンプルサイズの決め方3章では母分散が既知の時の母平均の検定の手順は以下のように紹介されています。

  • 手順1:仮説の設定

    • 帰無仮説 H₀:μ = μ₀μ₀ は指定された値)
    • 対立仮説 (1) H₁:μ ≠ μ₀
    • 対立仮説 (2) H₁:μ > μ₀
    • 対立仮説 (3) H₁:μ < μ₀
  • 手順2:有意水準αの設定(通常はα = 0.05とする)

  • 手順3:棄却域Rの設定

    • 対立仮説 (1) の場合 R:|u₀| ≥ z_{α/2}
    • 対立仮説 (2) の場合 R:u₀ ≥ z_{α}
    • 対立仮説 (3) の場合 R:u₀ ≤ z_{₁-α}(= -z_{α})
  • 手順4:データx₁, x₂, ···, xₙをとり、検定統計量u_₀の値を計算する。
    u₀ = \frac{(x̄ - μ₀)}{\sqrt{(σ₀²/n)}} (σ_₀^²は既知の母分散の値)

  • 手順5:u₀が手順3で設定した棄却域Rにあれば有意と判定し、H_₀を棄却する。

この検定では、u₀ = \frac{(x̄ - μ₀)}{\sqrt{(σ₀²/n)}}は標準正規分布に従うことを利用しています。
pythonで実装すると以下のようになります。

import numpy as np
from scipy import stats

def hypothesis_test(data, mu0, sigma0, alpha=0.05, test_type='two-sided'):
    n = len(data)
    x_bar = np.mean(data)
    
    u0 = (x_bar - mu0) / (sigma0 / np.sqrt(n))
    
    if test_type == 'two-sided':
        critical_value = stats.norm.ppf(1 - alpha/2)
        reject = abs(u0) >= critical_value
    elif test_type == 'greater':
        critical_value = stats.norm.ppf(1 - alpha)
        reject = u0 >= critical_value
    elif test_type == 'less':
        critical_value = stats.norm.ppf(alpha)
        reject = u0 <= critical_value
    else:
        raise ValueError("Invalid test_type. Choose 'two-sided', 'greater', or 'less'.")

    return {
        'test_statistic': u0,
        'critical_value': critical_value,
        'reject_null': reject
    }

そこで、実際にこの関数を用いて練習問題を解いていきたいと思います。

\begin{aligned} &\text{問題3.1} \\ &n = 10 \text{ の下記のデータに基づいて、} H_0:\mu = \mu_0 \: (\mu_0 = 5.0)\text{、} H_1:\mu \neq \mu_0 \text{ を} \\ &\text{有意水準 } 5\% \text{ で検定せよ。ただし、母分散は } \sigma_0^2 = 1.0^2 \text{ と既知である。} \\ &\text{データ:} 6.2, 4.8, 7.3, 5.5, 6.5, 4.9, 6.8, 7.9, 6.6, 7.3 \end{aligned}
print("問題3.1の結果:")
data_3_1 = [6.2, 4.8, 7.3, 5.5, 6.5, 4.9, 6.8, 7.9, 6.6, 7.3]
mu0_3_1 = 5.0
sigma0_3_1 = 1.0
result_3_1 = hypothesis_test(data_3_1, mu0_3_1, sigma0_3_1, alpha=0.05, test_type='two-sided')

print(f"検定統計量 u0: {result_3_1['test_statistic']:.4f}")
print(f"棄却域の境界: ±{result_3_1['critical_value']:.4f}")
print(f"帰無仮説を棄却するか: {'はい' if result_3_1['reject_null'] else 'いいえ'}")
結果
問題3.1の結果:
検定統計量 u0: 4.3639
棄却域の境界: ±1.9600
帰無仮説を棄却するか: はい

この問題は対立仮説がH₁:μ ≠ μ₀となっているため、|u₀| ≥ z_{α/2}の時に帰無仮説を棄却することができます。この問題の検定統計量は4.3639となっており、1.96よりも大きいため、帰無仮説を棄却します。
次に、練習問題3-2を同様に解いていきます。

\begin{aligned} &\text{問題3.2} \\ &n = 9 \text{ の下記のデータに基づいて、} H_0:\mu = \mu_0 \: (\mu_0 = 10.0)\text{、} H_1:\mu > \mu_0 \text{ を} \\ &\text{有意水準 } 5\% \text{ で検定せよ。ただし、母分散は } \sigma_0^2 = 0.7^2 \text{ と既知である。} \\ &\text{データ:} 10.8, 11.2, 9.7, 9.9, 12.0, 9.6, 10.5, 10.7, 10.1 \end{aligned}
print("問題3.2の結果:")
data_3_2 = [10.8, 11.2, 9.7, 9.9, 12.0, 9.6, 10.5, 10.7, 10.1]
mu0_3_2 = 10.0
sigma0_3_2 = 0.7
result_3_2 = hypothesis_test(data_3_2, mu0_3_2, sigma0_3_2, alpha=0.05, test_type='greater')

print(f"検定統計量 u0: {result_3_2['test_statistic']:.4f}")
print(f"棄却域の境界: {result_3_2['critical_value']:.4f}")
print(f"帰無仮説を棄却するか: {'はい' if result_3_2['reject_null'] else 'いいえ'}")
結果
問題3.2の結果:
検定統計量 u0: 2.1429
棄却域の境界: 1.6449
帰無仮説を棄却するか: はい

この問題は対立仮説がH₁:μ > μ₀となっているため、u₀ ≥ z_{α}の時に帰無仮説を棄却することができます。3-2の検定統計量は2.1429となり、棄却域の境界である1.64より大きいため、帰無仮説を棄却します。
3-3も同様に解くと以下のようになります。

\begin{aligned} &\text{問題3.3} \\ &n = 8 \text{ の下記のデータに基づいて、} H_0:\mu = \mu_0 \: (\mu_0 = 20.0)\text{、} H_1:\mu < \mu_0 \text{ を} \\ &\text{有意水準 } 5\% \text{ で検定せよ。ただし、母分散は } \sigma_0^2 = 2.0^2 \text{ と既知である。} \\ &\text{データ:} 21, 19, 16, 19, 22, 18, 20, 21 \end{aligned}
print("問題3.3の結果:")
data_3_3 = [21, 19, 16, 19, 22, 18, 20, 21]
mu0_3_3 = 20.0
sigma0_3_3 = 2.0
result_3_3 = hypothesis_test(data_3_3, mu0_3_3, sigma0_3_3, alpha=0.05, test_type='less')

print(f"検定統計量 u0: {result_3_3['test_statistic']:.4f}")
print(f"棄却域の境界: {result_3_3['critical_value']:.4f}")
print(f"帰無仮説を棄却するか: {'はい' if result_3_3['reject_null'] else 'いいえ'}")
結果
問題3.3の結果:
検定統計量 u0: -0.7071
棄却域の境界: -1.6449
帰無仮説を棄却するか: いいえ

この問題は対立仮説がH₁:μ < μ₀となっているため、R:u₀ ≤ z_{₁-α}(= -z_{α})の時に帰無仮説を棄却することができます。検定統計量は-0.7071となり、-1.6449よりも大きいため、こちらは帰無仮説を棄却することができません。

検出力の計算

次に、検出力の計算について解説します。検出力(1 - β)は対立仮説H_1のもとで計算した「帰無仮説H_0を棄却する確率」と紹介されており、以下のように定義されています。

\begin{aligned} 1 - \beta &= Pr(u \leq -z_{\alpha/2} - \sqrt{n}\Delta) + Pr(u \geq z_{\alpha/2} - \sqrt{n}\Delta) & \text{(両側検定)}\\ 1 - \beta &= Pr(u \geq z_{\alpha} - \sqrt{n}\Delta) & \text{(片側検定 }H_{0} : \mu > \mu_0\text{)} \\ 1 - \beta &= Pr(u \leq -z_{\alpha} - \sqrt{n}\Delta) & \text{(片側検定 }H_{0} : \mu < \mu_0\text{)} \\ \end{aligned}

ただし、\Deltaは以下のように定義しています。

\Delta = \frac{(\mu - \mu_{0})}{\sigma_{0}}

これらのことを踏まえて、実際に例題をpythonを用いて解いていきたいと思います。
検出力を計算するプログラムは以下のようになります。

import numpy as np
from scipy import stats

def calculate_power(n, alpha, delta, test_type='two-sided'):
    """
    検出力を計算する関数

    n: サンプルサイズ
    alpha: 有意水準
    delta: Δ
    test_type: 検定の種類 ('two-sided', 'greater', 'less')
    return: 検出力 (1 - β)
    """
    if test_type == 'two-sided':
        z_alpha = stats.norm.ppf(1 - alpha / 2)
        power = (1 - stats.norm.cdf(z_alpha - np.sqrt(n) * delta) +
                 stats.norm.cdf(-z_alpha - np.sqrt(n) * delta))
    elif test_type == 'greater':
        z_alpha = stats.norm.ppf(1 - alpha)
        power = 1 - stats.norm.cdf(z_alpha - np.sqrt(n) * delta)
    elif test_type == 'less':
        z_alpha = stats.norm.ppf(1 - alpha)
        power = stats.norm.cdf(-z_alpha - np.sqrt(n) * delta)
    else:
        raise ValueError("Invalid test_type. Choose 'two-sided', 'greater', or 'less'.")
    
    return power

そこで、上で定義した関数を用いて、練習問題3-5から問いていきたいと思います。

\begin{aligned} &\text{問題3.5} \\ &\text{帰無仮説と対立仮説を } H_0:\mu = \mu_0 \: (\mu_0 = 5.0)\text{、} H_1:\mu \neq \mu_0 \text{ と設定し、有意水準 } 5\% \text{ で} \\ &\text{検定する。ただし、母分散は } \sigma_0^2 = 1.0^2 \text{ と既知である。} \\ &\text{(1) } n = 10\text{、}\Delta = (\mu - \mu_0)/\sigma_0 = 0.5 \text{ の場合に検出力を求めよ。} \\ &\text{(2) } n = 20\text{、}\Delta = (\mu - \mu_0)/\sigma_0 = 0.5 \text{ の場合に検出力を求めよ。} \end{aligned}
print("問題3.5の結果:")
alpha_3_5 = 0.05
delta_3_5 = 0.5

# (1) n = 10
n_3_5_1 = 10
power_3_5_1 = calculate_power(n_3_5_1, alpha_3_5, delta_3_5, 'two-sided')
print(f"(1) n = 10 の場合の検出力: {power_3_5_1:.4f}")

# (2) n = 20
n_3_5_2 = 20
power_3_5_2 = calculate_power(n_3_5_2, alpha_3_5, delta_3_5, 'two-sided')
print(f"(2) n = 20 の場合の検出力: {power_3_5_2:.4f}")
結果
問題3.5の結果:
(1) n = 10 の場合の検出力: 0.3526
(2) n = 20 の場合の検出力: 0.6088

この問題ではサンプルサイズを増やすことで検出力が向上することが確認できました。

\begin{aligned} &\text{3.6 帰無仮説と対立仮説を } H_0:\mu = \mu_0 \: (\mu_0 = 10.0)\text{、} H_1:\mu > \mu_0 \text{ と設定し、有意水準 } 5\% \text{ で} \\ &\text{検定する。ただし、母分散は } \sigma_0^2 = 0.7^2 \text{ と既知である。} \\ &\text{(1) } n = 9\text{、}\Delta = (\mu - \mu_0)/\sigma_0 = 1.0 \text{ の場合に検出力を求めよ。} \\ &\text{(2) } n = 9\text{、}\Delta = (\mu - \mu_0)/\sigma_0 = 1.5 \text{ の場合に検出力を求めよ。} \end{aligned}
# 問題3.6
print("問題3.6の結果:")
alpha_3_6 = 0.05
n_3_6 = 9

# (1) Δ = 1.0
delta_3_6_1 = 1.0
power_3_6_1 = calculate_power(n_3_6, alpha_3_6, delta_3_6_1, 'greater')
print(f"(1) Δ = 1.0 の場合の検出力: {power_3_6_1:.4f}")

# (2) Δ = 1.5
delta_3_6_2 = 1.5
power_3_6_2 = calculate_power(n_3_6, alpha_3_6, delta_3_6_2, 'greater')
print(f"(2) Δ = 1.5 の場合の検出力: {power_3_6_2:.4f}")
結果
問題3.6の結果:
(1) Δ = 1.0 の場合の検出力: 0.9123
(2) Δ = 1.5 の場合の検出力: 0.9978

Δが大きくなると検出力が上がることがわかります。

\begin{aligned} &\text{3.7 帰無仮説と対立仮説を } H_0:\mu = \mu_0 \: (\mu_0 = 20.0)\text{、} H_1:\mu < \mu_0 \text{ と設定し、有意水準 } 5\% \text{ で} \\ &\text{検定する。ただし、母分散は } \sigma_0^2 = 2.0^2 \text{ と既知である。} \\ &\text{(1) } n = 8\text{、}\Delta = (\mu - \mu_0)/\sigma_0 = -1.0 \text{ の場合に検出力を求めよ。} \\ &\text{(2) } n = 16\text{、}\Delta = (\mu - \mu_0)/\sigma_0 = -1.0 \text{ の場合に検出力を求めよ。} \end{aligned}
# 問題3.7
print("問題3.7の結果:")
alpha_3_7 = 0.05
delta_3_7 = -1.0

# (1) n = 8
n_3_7_1 = 8
power_3_7_1 = calculate_power(n_3_7_1, alpha_3_7, delta_3_7, 'less')
print(f"(1) n = 8 の場合の検出力: {power_3_7_1:.4f}")

# (2) n = 16
n_3_7_2 = 16
power_3_7_2 = calculate_power(n_3_7_2, alpha_3_7, delta_3_7, 'less')
print(f"(2) n = 16 の場合の検出力: {power_3_7_2:.4f}")
結果
問題3.7の結果:
(1) n = 8 の場合の検出力: 0.8817
(2) n = 16 の場合の検出力: 0.9907

サンプルサイズを2倍にすることで、検出力が大幅に向上しています。

サンプルサイズの設計方法

書籍ではサンプルサイズの設計方法は以下のように紹介されています。

\begin{aligned} &\text{両側検定 } (H_1: \mu \neq \mu_0) \text{ の場合:} & n &\approx \left(\frac{z_{\alpha/2} - z_{1-\beta}}{\Delta_0}\right)^2 & z_{\alpha/2} - \sqrt{n}\Delta_0 &\approx z_{1-\beta} \\[1.5em] &\text{片側検定 } (H_1: \mu > \mu_0) \text{ の場合:} & n &= \left(\frac{z_{\alpha} - z_{1-\beta}}{\Delta_0}\right)^2 & z_{\alpha} - \sqrt{n}\Delta_0 &= z_{1-\beta} \\[1.5em] &\text{片側検定 } (H_1: \mu < \mu_0) \text{ の場合:} & n &= \left(\frac{z_{\alpha} - z_{1-\beta}}{\Delta_0}\right)^2 & z_{1-\alpha} + \sqrt{n}\Delta_0 &= z_{\beta} \end{aligned}

これをpythonで実装したプログラムは以下の通りです。

import math
from scipy import stats

def calculate_sample_size(alpha, beta, delta, test_type):
    z_alpha = stats.norm.ppf(1 - alpha)
    z_beta = stats.norm.ppf(1 - beta)
    
    if test_type == "two_sided":
        z_alpha = stats.norm.ppf(1 - alpha/2)
    
    # 初期値の設定
    n_min, n_max = 2, 1000
    
    while n_min <= n_max:
        n = (n_min + n_max) // 2
        if test_type == "two_sided":
            power = 1 - stats.norm.cdf(z_alpha - math.sqrt(n) * delta) + stats.norm.cdf(-z_alpha - math.sqrt(n) * delta)
        else:  
            power = 1 - stats.norm.cdf(z_alpha - math.sqrt(n) * delta)
        
        if abs(power - (1 - beta)) < 0.0001:
            return n
        elif power < (1 - beta):
            n_min = n + 1
        else:
            n_max = n - 1
    
    return n_min  

この関数を用いて以下の練習問題を解いていきます。

\begin{aligned} &\text{3.8 帰無仮説と対立仮説を } H_0:\mu = \mu_0 \: (\mu_0 = 5.0)\text{、} H_1:\mu \neq \mu_0 \text{ と設定し、有意水準 } 5\% \text{ で} \\ &\text{検定する。ただし、母分散は } \sigma_0^2 = 1.0^2 \text{ と既知である。} \\[0.5em] &\text{(1) } |\Delta| = |\mu - \mu_0|/\sigma_0 \geq 0.8 \text{ のとき検出力が } 0.90 \text{ となるように} \\ &\quad\text{サンプルサイズ } n \text{ を定めよ。} \\[0.5em] &\text{(2) } |\Delta| = |\mu - \mu_0|/\sigma_0 \geq 0.8 \text{ のとき検出力が } 0.95 \text{ となるように} \\ &\quad\text{サンプルサイズ } n \text{ を定めよ。} \end{aligned}
print("問題 3.8:")
alpha = 0.05
delta = 0.8

# (1) Power = 0.90
n1 = calculate_sample_size(alpha, 0.10, delta, "two_sided")
print(f"(1) 検出力0.90のサンプルサイズ: {n1}")

# (2) Power = 0.95
n2 = calculate_sample_size(alpha, 0.05, delta, "two_sided")
print(f"(2) 検出力0.95のサンプルサイズ: {n2}")
結果
問題 3.8:
(1) 検出力0.90のサンプルサイズ: 17
(2) 検出力0.95のサンプルサイズ: 21

この結果は、検出力を高めるためにはサンプルサイズを増やす必要があることを示しています。

\begin{aligned} &\text{3.9 帰無仮説と対立仮説を } H_0:\mu = \mu_0 \: (\mu_0 = 10.0)\text{、} H_1:\mu > \mu_0 \text{ と設定し、有意水準 } 5\% \text{ で} \\ &\text{検定する。ただし、母分散は } \sigma_0^2 = 0.7^2 \text{ と既知である。} \\[0.5em] &\text{(1) } \Delta = (\mu - \mu_0)/\sigma_0 \geq 1.0 \text{ のとき検出力が } 0.90 \text{ となるように} \\ &\quad\text{サンプルサイズ } n \text{ を定めよ。} \\[0.5em] &\text{(2) } \Delta = (\mu - \mu_0)/\sigma_0 \geq 0.5 \text{ のとき検出力が } 0.90 \text{ となるように} \\ &\quad\text{サンプルサイズ } n \text{ を定めよ。} \end{aligned}
print("問題 3.9:")
alpha = 0.05
beta = 0.10  # Power = 1 - beta = 0.90

# (1) Delta = 1.0
n1 = calculate_sample_size(alpha, beta, 1.0, "one_sided")
print(f"(1) Δ >= 1.0 かつ検出力 0.90 の場合のサンプルサイズ: {n1}")

# (2) Delta = 0.5
n2 = calculate_sample_size(alpha, beta, 0.5, "one_sided")
print(f"(2) Δ >= 0.5 かつ検出力 0.90 の場合のサンプルサイズ: {n2}")
結果
問題 3.9:
(1) Δ >= 1.0 かつ検出力 0.90 の場合のサンプルサイズ: 9
(2) Δ >= 0.5 かつ検出力 0.90 の場合のサンプルサイズ: 35

Δが小さい場合、十分な検出力を得るためにはサンプルサイズを大幅に増やす必要があることがわかります。

\begin{aligned} &\text{3.10 帰無仮説と対立仮説を } H_0:\mu = \mu_0 \: (\mu_0 = 20.0)\text{、} H_1:\mu < \mu_0 \text{ と設定し、有意水準 } 5\% \text{ で} \\ &\text{検定する。ただし、母分散は } \sigma_0^2 = 2.0^2 \text{ と既知である。} \\[0.5em] &\text{(1) } \Delta = (\mu - \mu_0)/\sigma_0 \leq -1.2 \text{ のとき検出力が } 0.90 \text{ となるように} \\ &\quad\text{サンプルサイズ } n \text{ を定めよ。} \\[0.5em] &\text{(2) } \Delta = (\mu - \mu_0)/\sigma_0 \leq -1.5 \text{ のとき検出力が } 0.95 \text{ となるように} \\ &\quad\text{サンプルサイズ } n \text{ を定めよ。} \end{aligned}
print("問題 3.10:")
alpha = 0.05

# (1) Delta = -1.2, Power = 0.90
n1 = calculate_sample_size(alpha, 0.10, 1.2, "one_sided")
print(f"(1) Δ ≤ -1.2 かつ検出力 0.90 の場合のサンプルサイズ: {n1}")

# (2) Delta = -1.5, Power = 0.95
n2 = calculate_sample_size(alpha, 0.05, 1.5, "one_sided")
print(f"(2) Δ ≤ -1.5 かつ検出力 0.95 の場合のサンプルサイズ: {n2}")
結果
問題 3.10:
(1) Δ ≤ -1.2 かつ検出力 0.90 の場合のサンプルサイズ: 6
(2) Δ ≤ -1.5 かつ検出力 0.95 の場合のサンプルサイズ: 5

最後に

本ブログでは、永田靖著『サンプルサイズの決め方』の第3章「一つの母平均の検定-母分散が既知の場合」の内容を、Pythonを用いて実践的に解説しました。ここで学んだ主要なポイントは以下の通りです:

  1. 母平均の検定の基本概念と手順
  2. 検出力の計算方法とその重要性
  3. 適切なサンプルサイズの設計方法

次回のブログでは、『サンプルサイズの決め方』の第4章の内容を取り上げる予定です。このブログを通して少しでもサンプルサイズの設計方法について理解が進めば幸いです。

DMM Data Blog

Discussion