t検定をPythonで実行してみよう(scipy.stats.ttest)

t検定をPythonで実行してみよう(scipy.stats.ttest)

データ分析をしていると、「AとBに本当に差があるのか?」という疑問に出会うことがよくあります。

たとえば……

新しい教材を使ったクラスと従来の教材を使ったクラスで、
 テストの平均点に差はあるのか?

薬Aと薬Bで、
 効果に違いはあるのか?

……といった場面です。

こうした疑問に、感覚ではなく数値的な根拠をもって答える方法t検定(ティーけんてい) です。

今回は、t検定の基本的な考え方と、SciPyを使って実際にPythonで実行する方法を、できるだけ簡単に解説します。

t検定とは?

 ひとことで言うと

t検定 とは、2つのグループの平均値に「統計的に意味のある差」があるかどうかを判定する方法です。

ここでのポイントは「統計的に意味のある差」という部分です。

 

 なぜ「平均が違う=差がある」と言えないのか?

たとえば、次の2クラスのテスト結果を見てみましょう。

  • クラスA の平均点:76.0点
  • クラスB の平均点:79.0点

一見すると「クラスBのほうが優秀だ」と思えますが、本当にそう言い切れるでしょうか?

実は、この3点の差は 「たまたま」生じた誤差(偶然のばらつき) かもしれません。

もし別の日にもう一度テストをしたら、今度はクラスAのほうが高い、ということも起こりえます。

t検定は、この「本当に差があるのか、偶然なのか」を確率的に判定してくれます。

 

t検定を理解するための3つの重要キーワード

t検定を使いこなすには、以下の3つの概念を知っておく必要があります。

 ① 帰無仮説(きむかせつ)と対立仮説(たいりつかせつ)

t検定では、最初に 2つの仮説 を立てます。

用語 英語 意味
帰無仮説(H₀) Null Hypothesis 「2つのグループに差はない」という仮説
対立仮説(H₁) Alternative Hypothesis 「2つのグループに差がある」という仮説

t検定の目的は、帰無仮説を否定(棄却)できるかどうかを判定することです。

帰無仮説を否定できれば、「差がない」という前提が崩れるため、「差がある(=対立仮説が正しい)」と結論づけることができます。

少し回りくどく感じるかもしれませんが、「差がある」ことを直接証明するのは難しいので、「差がない」を否定することで、間接的に「差がある」を示すというのが統計学のアプローチです。

【t検定の論理の流れ】

(1)仮説を立てる:「2つのグループに差はない」(帰無仮説)
(2)検定を実行:データから確率(p値)を計算する
(3)判定する:p値が小さければ、帰無仮説を棄却し「差がある」と結論づける

 

 ② p値(ピーち)

p値(p-value) は、帰無仮説が正しいと仮定したとき、今回のデータのような差が偶然に生じる確率です。

p値が小さいほど「偶然でこんな差が出るのは考えにくい」、つまり「本当に差がある」と判断します。

【p値の直感的なイメージ】
  • p値 = 0.80(80%) → 偶然でも普通に起こる差 → 差があるとは言えない
  • p値 = 0.30(30%) → まあまあ起こりうる差 → 差があるとは言えない
  • p値 = 0.04(4%) → 偶然では起こりにくい差 → 差がある!
  • p値 = 0.001(0.1%)→ 偶然ではほぼ起こらない → 差がある!!

 

 ③ 有意水準(ゆういすいじゅん)

有意水準 とは、「p値がいくつ以下なら差があると判定するか」という判断の基準値のことです。

一般的に、有意水準 = 0.05(5%) がよく使われます。

【判定ルール(有意水準 = 0.05 の場合)】
  • p値 < 0.05 → 帰無仮説を棄却 → 「統計的に有意な差がある」
  • p値 ≥ 0.05 → 帰無仮説を棄却できない → 「有意な差があるとは言えない」

 

補足:「有意」とは?
「有意(ゆうい)」とは「統計的に意味がある」ということです。英語では “statistically significant” と言います。日常の「意味がある」とはニュアンスが異なり、「偶然とは考えにくいレベルの差がある」という統計学の専門的な意味で使われます。

 

補足:「棄却できない」≠「差がない」
p値が0.05以上だったとき、「差がない」と断言するのは誤りです。正しくは「差があるとは言えない(=証拠が不十分)」です。データが少ない場合など、本当は差があっても検出できないことがあるためです。

 

t検定の種類

SciPyでは、状況に応じて2種類のt検定を使い分けます。

 対応のないt検定(独立2標本t検定)

異なる2つのグループを比較するときに使います。

  • 特徴:2つのグループに含まれる人は別々(同じ人は含まれない)
  • SciPyの関数:stats.ttest_ind()(ind = independent=独立)

<<使用例>>

  • クラスAとクラスBのテスト成績を比較する
  • 薬Aを飲んだグループと薬Bを飲んだグループの効果を比較する
  • 男性グループと女性グループの購買額を比較する

 

 対応のあるt検定(対応2標本t検定)

同じグループの「前」と「後」を比較するときに使います。

  • 特徴:同じ対象を2回測定している(ペアデータ)
  • SciPyの関数:stats.ttest_rel()(rel = related=関連がある)

<<使用例>>

  • 同じ生徒の「勉強前」と「勉強後」のテスト成績を比較する
  • 同じ患者の「投薬前」と「投薬後」の血圧を比較する
  • 同じ店舗の「キャンペーン前」と「キャンペーン後」の売上を比較する

 

実践例

 対応のないt検定(ttest_ind)

ある学校で、クラスA(従来の教材)とクラスB(新しい教材)のテスト成績に差があるかを調べたいとします。

以下、コードです。

from scipy import stats

# クラスAの点数(従来の教材):10人
class_a = [65, 70, 68, 72, 74, 71, 69, 73, 67, 75]

# クラスBの点数(新しい教材):10人
class_b = [78, 82, 80, 85, 79, 83, 88, 76, 84, 81]

# 対応のないt検定を実行
t_stat, p_value = stats.ttest_ind(class_a, class_b)

print(f"t統計量:\t{t_stat:.4f}")
print(f"p値: \t{p_value:.4f}")
  • class_a = [65, 70, ...]:クラスA(10人分)の点数データをリストで用意します
  • class_b = [78, 82, ...]:クラスB(10人分)の点数データをリストで用意します
  • t_stat, p_value = stats.ttest_ind(class_a, class_b)ttest_ind() 関数に2つのグループのデータを渡し、結果として t統計量p値 の2つの値を受け取りま
  • print(...):結果を表示します

 

以下、実行結果です。

t統計量:	-7.3886
p値: 	0.0000

 

p値を有意水準 0.05(5%)と比較すると、p値のほうがはるかに小さいです。

→ 帰無仮説を棄却
→「クラスAとクラスBのテスト成績には統計的に有意な差がある」

つまり、新しい教材を使ったクラスBのほうが成績が良いのは、偶然ではなく意味のある差だと判断できます。

 

補足:t統計量とは?
t統計量(t-statistic)は、2つのグループの平均値の差が、データのばらつきに対してどれくらい大きいかを表す数値です。t統計量の絶対値が大きいほど、差が大きいことを意味します。符号(プラス・マイナス)は、どちらのグループが大きいかを示します(今回はマイナスなので、第1引数のclass_aのほうが小さい)。実際の判定には主にp値を使うので、まずはp値の読み方を覚えれば十分です。

 

 対応のあるt検定(ttest_rel)

あるプログラミング講座で、受講前と受講後のスキルテストの点数に差があるかを調べたいとします。

以下、コードです。

from scipy import stats

# 受講前のテスト点数(8人分)
before = [55, 60, 58, 62, 65, 57, 61, 59]

# 受講後のテスト点数(同じ8人)
after = [70, 68, 72, 75, 78, 65, 74, 71]

# 対応のあるt検定を実行
t_stat, p_value = stats.ttest_rel(before, after)

print(f"t統計量:\t{t_stat:.4f}")
print(f"p値: \t{p_value:.4f}")
  • before = [55, 60, ...]:受講前のテスト点数(8人分)
  • after = [70, 68, ...]:受講後のテスト点数(同じ8人の点数)
  • stats.ttest_rel(before, after)対応のあるt検定を実行。ttest_ind ではなく ttest_rel を使う点に注意してください
  • 重要なのは、beforeafter同じ人の「前」と「後」のペアになっていることです(1番目の55と70は同じ人の点数)

 

以下、実行結果です。

t統計量:	-12.9615
p値: 	0.0000

 

p値を有意水準 0.05(5%)と比較すると、p値のほうがはるかに小さいです。

→ 帰無仮説を棄却
→「受講前と受講後のテスト成績には統計的に有意な差がある」

プログラミング講座の受講によって、テスト成績が偶然ではなく有意に向上したと判断できます。

 

 差が見られないケース

ここまで「差がある」例ばかり見てきたので、差があるとは言えないケースも確認しておきましょう。

2つのチームの月間売上に差があるかを調べます。

以下、コードです。

from scipy import stats

# チームXの月間売上(万円)
team_x = [120, 135, 128, 140, 132, 125, 138, 130]

# チームYの月間売上(万円)
team_y = [130, 125, 136, 133, 129, 140, 127, 134]

# 対応のないt検定を実行
t_stat, p_value = stats.ttest_ind(team_x, team_y)

print(f"t統計量:\t{t_stat:.4f}")
print(f"p値: \t{p_value:.4f}")

 

以下、実行結果です。

t統計量:	-0.2547
p値: 	0.8026

 

p値は、有意水準0.05をはるかに超えています。

つまり、この程度の売上差は偶然のばらつきの範囲内であり、「2つのチームの売上に意味のある差がある」とは言えません。

 

t検定を使うときの注意点

t検定は便利なツールですが、正しく使うためにいくつかの前提条件があります。

 ① データが正規分布に近いこと

t検定は、データが正規分布(釣り鐘型の分布)に近いことを前提としています。

極端に偏ったデータでは、結果が正確でなくなる可能性があります。

ただし、データの件数が十分に多い場合(目安として各グループ30件以上)は、多少正規分布から外れていても問題ないとされています。

 

 ② データの件数が少なすぎないこと

各グループのデータが極端に少ない(3〜4件など)場合、検定の信頼性が低くなります。

少なくとも各グループ5件以上、できれば30件以上あることが望ましいです。

 

 ③ 対応のないt検定では、等分散性に注意

ttest_ind() はデフォルトで2つのグループの分散が等しいことを仮定しています。

分散が大きく異なる可能性がある場合は、equal_var=False を指定します。

# 分散が等しくない可能性がある場合(ウェルチのt検定)
t_stat, p_value = stats.ttest_ind(class_a, class_b, equal_var=False)

 

この指定をすると、ウェルチのt検定(分散が等しくなくても使える、より汎用的なt検定)が実行されます。

迷ったときは equal_var=False をつけておくほうが安全です。

 

補足:等分散性(とうぶんさんせい)とは?
等分散性とは、2つのグループのデータのばらつき(分散)がほぼ同じであるという性質のことです。たとえば、クラスAの点数が60〜80点の範囲に収まっていて、クラスBの点数が40〜100点の範囲に広がっている場合、2つのグループの分散は等しくありません。

 

よくある間違いと注意点

 ❌「p値が大きい=差がない」ではない

p値が0.05以上でも、「差がない」とは断言できません。

「今回のデータでは差があるとは言えなかった」というだけです。サンプル数を増やしたら有意になる可能性もあります。

 

 ❌「p値が小さい=大きな差がある」ではない

p値が非常に小さくても、実際の差が小さいことはあります。

サンプル数が非常に多いと、わずかな差でも統計的に有意になるためです。p値は「差の大きさ」ではなく「差の確実さ」を示すものです。

 

 ❌ 3つ以上のグループにt検定を繰り返してはいけない

「A vs B」「B vs C」「A vs C」のように、t検定を何度も繰り返すと、偶然有意になる確率が高くなります。

3つ以上のグループを比較する場合は、分散分析(ANOVA)という別の手法を使います。

 

まとめ

今回のポイントを振り返りましょう。

  • t検定 は、2つのグループの平均値に統計的に意味のある差があるかを判定する方法
  • 帰無仮説(差はない)を p値 に基づいて棄却するかどうかで判断する
  • p値 < 0.05 なら「有意な差がある」と判定するのが一般的
  • 対応のないt検定ttest_ind):異なる2グループの比較
  • 対応のあるt検定ttest_rel):同じ対象の前後比較
  • 分散が等しくない可能性があるときは equal_var=False(ウェルチのt検定)を使う

次回は、「カイ二乗検定でカテゴリデータを分析する」 をテーマに、数値ではなくカテゴリ(分類)データの関連性を調べる方法を学んでいきます。