Pythonで統計的な検定を行う(SciPy活用)
Pythonは、その豊富なライブラリ群によって、統計分析においても強力なツールとなります。特に、SciPyライブラリは、科学技術計算全般をカバーしており、統計的な検定を行うための多様な関数を提供しています。本稿では、SciPyを用いた主要な統計的検定について、その理論的背景、実装方法、および応用例を詳細に解説します。
1. 統計的検定の基本概念
統計的検定は、ある仮説(帰無仮説)がデータから棄却されるべきかどうかを判断するための統計的手法です。検定の目的は、偶然では説明できないほど、観測されたデータが帰無仮説と矛盾するかどうかを評価することにあります。
1.1. 帰無仮説と対立仮説
帰無仮説 (Null Hypothesis, H0)は、通常、「差がない」「関連がない」といった、検証したい効果がないことを主張する仮説です。一方、対立仮説 (Alternative Hypothesis, H1)は、帰無仮説とは反対の主張であり、「差がある」「関連がある」といった、検証したい効果があることを主張する仮説です。
1.2. p値
p値 (p-value)は、帰無仮説が真であると仮定した場合に、観測されたデータまたはそれ以上に極端なデータが得られる確率です。p値が小さいほど、観測されたデータは帰無仮説と矛盾する度合いが強く、帰無仮説を棄却する根拠が強まります。一般的に、有意水準 (Significance Level, α)(通常0.05や0.01)と比較され、p値 < αであれば帰無仮説は棄却されます。
2. SciPyによる主要な統計的検定
SciPyは、scipy.statsモジュール内に、様々な統計的検定を行うための関数を提供しています。ここでは、代表的な検定について説明します。
2.1. t検定
t検定は、2つのグループの平均値に統計的に有意な差があるかどうかを検定する手法です。データが正規分布に従うと仮定できる場合に用いられます。
2.1.1. 独立二標本t検定
2つの独立したグループの平均値を比較します。例えば、異なる治療法を受けた2つの患者群の回復率の平均を比較する場合などに使用されます。
from scipy import stats
# 例: データAとデータB
data_a = [ ... ]
data_b = [ ... ]
# 等分散を仮定しない場合 (Welch's t-test)
ttest_result_welch = stats.ttest_ind(data_a, data_b, equal_var=False)
print(f"Welch's t-test: statistic={ttest_result_welch.statistic}, pvalue={ttest_result_welch.pvalue}")
# 等分散を仮定する場合
ttest_result_equal = stats.ttest_ind(data_a, data_b, equal_var=True)
print(f"Equal variance t-test: statistic={ttest_result_equal.statistic}, pvalue={ttest_result_equal.pvalue}")
equal_var=Falseは、2つのグループの分散が等しくないことを仮定するWelch’s t-testを実行します。equal_var=Trueは、分散が等しいことを仮定します。
2.1.2. 対応のあるt検定 (ペアt検定)
同一の被験者から得られた2つの測定値の平均に差があるかを検定します。例えば、ある薬を投与する前と後の血圧の平均を比較する場合などに使用されます。
from scipy import stats
# 例: 投与前と投与後のデータ
before_drug = [ ... ]
after_drug = [ ... ]
ttest_result_paired = stats.ttest_rel(before_drug, after_drug)
print(f"Paired t-test: statistic={ttest_result_paired.statistic}, pvalue={ttest_result_paired.pvalue}")
2.2. ANOVA (分散分析)
ANOVAは、3つ以上のグループの平均値に差があるかを検定する手法です。t検定の拡張と考えることができます。
2.2.1. 一元配置分散分析 (One-Way ANOVA)
1つの要因(カテゴリカル変数)によって分けられた3つ以上のグループの平均値を比較します。
from scipy import stats
# 例: グループA, B, Cのデータ
group_a = [ ... ]
group_b = [ ... ]
group_c = [ ... ]
fvalue, pvalue = stats.f_oneway(group_a, group_b, group_c)
print(f"One-Way ANOVA: F-statistic={fvalue}, pvalue={pvalue}")
ANOVAで有意差が検出された場合、どのグループ間に差があるかを特定するために、事後検定 (Post-hoc tests)(例: Tukey’s HSD)を行うことが一般的ですが、SciPy単体では直接的な提供がなく、他のライブラリ(statsmodelsなど)を利用することが推奨されます。
2.3. カイ二乗検定
カイ二乗検定は、カテゴリカル変数間の関連性や、観測された度数が期待される度数と有意に異なるかどうかを検定する手法です。
2.3.1. 独立性のカイ二乗検定
2つのカテゴリカル変数が互いに独立であるかどうかを検定します。例えば、「喫煙習慣」と「肺がんの有無」の間に統計的な関連があるかを調べる場合などに使用されます。
from scipy import stats
import numpy as np
# 例: 観測度数表 (行: 喫煙習慣, 列: 肺がんの有無)
# 肺がんあり 肺がんなし
# 喫煙者 [ 50, 30 ]
# 非喫煙者 [ 10, 70 ]
observed = np.array([[50, 30], [10, 70]])
chi2, pvalue, dof, expected = stats.chi2_contingency(observed)
print(f"Chi-squared test of independence: chi2={chi2}, pvalue={pvalue}")
print("Expected frequencies:n", expected)
dofは自由度、expectedは帰無仮説(独立である)が真である場合に期待される度数です。
2.3.2. 適合度検定
観測された度数が、特定の理論分布(例えば、一様分布など)から期待される度数と有意に異なるかどうかを検定します。サイコロの各目が均等に出るかどうかの検定などに使用されます。
from scipy import stats
import numpy as np
# 例: サイコロの出目 (1から6) の観測度数
observed_counts = np.array([10, 15, 12, 8, 13, 12])
# 期待される度数 (一様分布の場合、各目の確率は 1/6)
expected_counts = np.array([10, 10, 10, 10, 10, 10]) # 例として合計60回とする
# SciPyのchisquare関数は、期待度数を渡すことも可能
chi2, pvalue = stats.chisquare(f_obs=observed_counts, f_exp=expected_counts)
print(f"Chi-squared goodness-of-fit test: chi2={chi2}, pvalue={pvalue}")
2.4. ノンパラメトリック検定
データが正規分布に従わない、あるいは順序尺度データである場合に用いられる検定です。SciPyでもいくつか提供されています。
2.4.1. Mann-Whitney U検定 (Wilcoxon順位和検定)
独立二標本t検定のノンパラメトリック版です。2つの独立したグループの分布に差があるかどうかを検定します。
from scipy import stats
# 例: データAとデータB (正規分布を仮定しない)
data_a_nonpara = [ ... ]
data_b_nonpara = [ ... ]
u_statistic, pvalue = stats.mannwhitneyu(data_a_nonpara, data_b_nonpara)
print(f"Mann-Whitney U test: U-statistic={u_statistic}, pvalue={pvalue}")
2.4.2. Wilcoxon符号順位検定
対応のあるt検定のノンパラメトリック版です。ペアとなったデータセットの分布に差があるかどうかを検定します。
from scipy import stats
# 例: 投与前と投与後のデータ (正規分布を仮定しない)
before_drug_nonpara = [ ... ]
after_drug_nonpara = [ ... ]
w_statistic, pvalue = stats.wilcoxon(before_drug_nonpara, after_drug_nonpara)
print(f"Wilcoxon signed-rank test: W-statistic={w_statistic}, pvalue={pvalue}")
3. 検定結果の解釈と注意点
統計的検定の結果を正しく解釈するには、いくつかの注意点があります。
3.1. p値の誤解
p値は「帰無仮説が真である場合に、観測されたデータまたはそれ以上に極端なデータが得られる確率」であり、「対立仮説が真である確率」や「帰無仮説が誤りである確率」ではありません。また、p値が有意水準より小さくても、それは「効果がない」という可能性を完全に排除するものではなく、あくまで「観測されたデータが、効果がないという仮説の下では起こりにくい」ということを示唆するものです。
3.2. 効果量
統計的有意性(p値)だけでなく、効果量 (Effect Size)も考慮することが重要です。効果量は、検出された差や関連性の大きさを、単位に依存しない形で示す指標です。例えば、Cohen’s dや相関係数などが挙げられます。SciPyでは直接的な効果量の計算関数は少ないですが、検定結果の統計量から計算することは可能です。
3.3. 検定の前提条件
多くの統計的検定には、データが満たすべき前提条件(例: 正規性、等分散性)があります。これらの前提条件が満たされない場合、検定結果の信頼性が低下する可能性があります。SciPyのドキュメンテーションで各関数の前提条件を確認し、必要に応じてノンパラメトリック検定やデータの変換を検討してください。
3.4. 多重比較問題
複数の検定を同時に行う場合、偶然有意な結果が得られる確率が高まります。これを多重比較問題 (Multiple Comparisons Problem)と呼びます。このような場合は、Bonferroni補正やBenjamini-Hochberg法などの多重比較法を適用してp値を調整する必要があります。これらの補正もstatsmodelsなどのライブラリで提供されています。
4. まとめ
SciPyライブラリは、Pythonで統計的検定を行うための強力かつ包括的なツールを提供します。t検定、ANOVA、カイ二乗検定、ノンパラメトリック検定など、様々な状況に対応する関数が利用可能です。これらの検定を適切に選択し、結果を正しく解釈することで、データに基づいた信頼性の高い結論を導き出すことができます。検定の前提条件の確認、効果量の考慮、多重比較問題への対処といった点に留意しながら、SciPyを活用して、より高度な統計分析を進めていきましょう。
