アンケートで「商品Aを選んだ人は男性に多かった」とき、それは本当に性別と好みに関係があるからでしょうか、それとも「たまたま」そう見えただけでしょうか。サイコロを120回振って6の目が15回しか出なかったとき、そのサイコロは不正と言えるのでしょうか、それとも公正なサイコロでも普通に起こりうる範囲なのでしょうか。
こうした「カテゴリごとに数えたデータ(カテゴリカルデータ)が、ある想定とどれくらい食い違っているか」を測り、その食い違いが偶然で説明できる範囲なのかを判定するのがカイ二乗検定(chi-square test)です。身長や重さのような連続量ではなく、「男性/女性」「商品A/B/C」「合格/不合格」のように数え上げた度数を扱うのが大きな特徴です。
この検定は驚くほど広い場面で活躍します。たとえば次のような応用先があります。
- マーケティング: 性別・年齢層と商品選好にクロス集計で関連があるか(A/Bテストの結果分析もこの仲間です)
- 遺伝学: メンデルの法則が予測する 9:3:3:1 の比に、実際の交配結果が従っているか
- 品質管理・医療: 不良品の発生がライン間で差があるか、ある治療と回復に関連があるか
本記事では、カイ二乗統計量 $\chi^2=\sum (O-E)^2/E$ が「何を測っているのか」という直感から出発し、適合度検定と独立性の検定という2つの代表的な使い方、自由度の決め方、結果の解釈に必要な p 値・有意水準、そして実務で必ず引っかかる「期待度数5以上」の条件・イェーツの連続性補正・効果量 Cramér’s V まで、図とPython実装を交えて一気通貫で解説します。
本記事の内容
- カイ二乗統計量 $\chi^2=\sum (O-E)^2/E$ の直感的な意味
- カイ二乗分布の定義と性質、自由度との関係
- 適合度検定と独立性の検定の手順(具体例つき)
- 自由度の決め方、p値・有意水準・帰無仮説の枠組み
- 期待度数5以上の条件、イェーツの連続性補正、効果量 Cramér’s V
scipy.stats.chisquare/chi2_contingencyを使ったPython実装
前提知識
この記事を読む前に、以下の記事を読んでおくと理解がスムーズになります。
カイ二乗検定は仮説検定という大きな枠組みの一例です。帰無仮説・対立仮説・p値・有意水準といった共通の考え方は 統計的検定とは?仮説検定の手順と考え方をわかりやすく解説 に詳しいので、本記事ではカイ二乗検定に固有の部分を重点的に扱います。
カイ二乗統計量は「ズレの大きさ」を測る物差し
まず、検定の細かい理屈に入る前に、カイ二乗検定の心臓部であるカイ二乗統計量が何をしているのかをイメージで掴みましょう。
あるカテゴリ分けされたデータについて、「理論や仮説からするとこれくらいの数になるはず」という期待度数 $E$ があり、一方で実際に観測した観測度数 $O$ があるとします。たとえば公正なサイコロなら各目は120回中20回ずつ出ると期待されますが($E=20$)、実際には15回や23回といった凸凹が出ます($O$)。
このとき知りたいのは「$O$ と $E$ のズレは、偶然のゆらぎで説明できる範囲か、それとも仮説そのものが間違っているサインか」です。そこで、各カテゴリのズレ $O-E$ を集計して1つの数値にまとめます。素朴に $O-E$ を足すとプラスとマイナスが打ち消し合って 0 になってしまうので、二乗してから足します。さらに、各ズレを期待度数 $E$ で割ってから足すのがポイントです。
$$ \chi^2 = \sum_{i} \frac{(O_i – E_i)^2}{E_i} $$
なぜ $E$ で割るのでしょうか。期待度数が 1000 の場所で 5 ズレるのと、期待度数が 10 の場所で 5 ズレるのとでは、後者のほうがはるかに「驚くべきズレ」です。$E$ で割ることで、「期待値に対してどれくらいの割合でズレたか」という相対的な驚きの大きさに変換しているのです。この割り算が、規模の違うカテゴリを公平に比べるための正規化になっています。
もう少し踏み込むと、この割り算には統計的な裏づけがあります。各カテゴリの度数はおおむね二項分布(あるいはポアソン分布)に従い、その分散は期待度数 $E$ にほぼ比例します。つまり「ズレの標準的な大きさ」は $\sqrt{E}$ の程度です。$(O-E)$ を $\sqrt{E}$ で割れば、ズレを「標準的なゆらぎ何個分か」という無次元量(標準化されたズレ)に直せます。その二乗が $(O-E)^2/E$ です。これは標準正規変数の二乗、すなわち自由度1のカイ二乗分布の素材そのものです。後でカイ二乗分布が登場するのは偶然ではなく、この標準化の構造から必然的に出てくるのです。

左の図では、各カテゴリで期待度数 $E$(グレー)と観測度数 $O$(青)の差を矢印で示しています。右の図は、その差を二乗して $E$ で割った各カテゴリの寄与 $(O-E)^2/E$ です。ズレが大きいカテゴリほど寄与が大きく、それらを全部足したものがカイ二乗統計量(この例では 2.70)になります。つまり $\chi^2$ は「全カテゴリのズレを総合した1つのスコア」であり、値が大きいほど「仮説とデータの食い違いが大きい」ことを意味します。
では、この $\chi^2$ という数字を「大きい/小さい」と判断する基準はどこから来るのでしょうか。それを与えてくれるのが、次に見るカイ二乗分布です。
カイ二乗分布
定義
カイ二乗統計量の値が「珍しいかどうか」を判断するには、「仮説が正しいときに $\chi^2$ がどんな値を取りやすいか」という基準分布が必要です。その基準になるのがカイ二乗分布で、実は標準正規分布から自然に作られます。
イメージとしては、平均0・分散1の標準正規分布から独立にいくつかの値を取り出し、それぞれを二乗して足し合わせる、という操作です。正規分布する誤差を二乗して集計する、という発想は、まさに先ほどの $(O-E)^2$ の集計と同じ構造をしています。
$Z_1, Z_2, \dots, Z_k$ が独立に標準正規分布 $N(0, 1)$ に従うとき、
$$ \chi^2 = Z_1^2 + Z_2^2 + \cdots + Z_k^2 $$
は自由度 $k$ のカイ二乗分布 $\chi^2(k)$ に従います。自由度 $k$ は「いくつの独立な正規変数を二乗して足したか」を表す数で、後で見るように検定では「自由に動けるカテゴリの数」として現れます。

この図は、2つの独立な標準正規変数 $Z_1, Z_2$ を二乗して足すと、自由度2のカイ二乗分布 $\chi^2(2)$ が得られる様子を表しています。左右対称だった正規分布が、二乗によって非負(0以上)の値だけを取り、右に長い裾を引く非対称な分布へと変わる点に注目してください。これがカイ二乗分布の基本的な姿です。
確率密度関数と性質
自由度 $k$ のカイ二乗分布の確率密度関数は次の形をしています。
$$ f(x) = \frac{1}{2^{k/2} \Gamma(k/2)} x^{k/2 – 1} e^{-x/2} \quad (x > 0) $$
ここで $\Gamma$ はガンマ関数です。この式そのものを暗記する必要はありませんが、いくつか押さえておくと便利な性質があります。
- 期待値: $E[\chi^2] = k$ — 自由度がそのまま平均になります。$k$ 個の標準正規変数の二乗和なので、各 $E[Z_i^2]=1$ を $k$ 個足して $k$ になる、と理解できます。
- 分散: $\mathrm{Var}(\chi^2) = 2k$ — 自由度が増えると、ばらつきも増えます。
- 非負: $\chi^2 \geq 0$ — 二乗和なので負になりません。
- 正規近似: $k$ が大きいとき、中心極限定理により正規分布 $N(k, 2k)$ に近づきます。
「期待値が $k$」という性質は実務でとても役立ちます。検定して得た $\chi^2$ の値が自由度 $k$ より大きく超えていれば「ズレが平均的な期待より大きい」、$k$ 程度かそれ以下なら「想定の範囲内」という大まかな感覚が、計算する前から持てるからです。たとえば自由度10の検定で $\chi^2 = 9$ が出たら、それは期待値10を下回るので「データは想定とよく合っている」と即座に判断できます。逆に $\chi^2 = 25$ なら期待値の2倍以上なので「これは怪しい」と当たりをつけられます。
なぜ二乗和という操作で正規分布が右に歪んだ分布へ変わるのか、もう少しイメージしておきましょう。標準正規分布では、値は0付近を取りやすく、±1や±2のような小さな絶対値が大半です。これを二乗すると、$0.5^2 = 0.25$ のように小さい値はさらに小さくなり、0付近にぐっと押し込まれます。一方、ごくまれに現れる $2$ や $3$ といった大きな値は $4$ や $9$ に拡大され、右側へ長い裾を作ります。負の値も二乗で正に折り返されるため、分布全体が0以上の領域に集約されます。こうして「0付近に山があり、右に長い裾を引く非対称な分布」が生まれるのです。
自由度による形の変化
カイ二乗分布の形は自由度 $k$ によって大きく変わります。実際にプロットして確かめてみましょう。
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
fig, ax = plt.subplots(figsize=(9, 5))
x = np.linspace(0.01, 25, 600)
for k in [1, 2, 3, 5, 10]:
ax.plot(x, stats.chi2.pdf(x, k), linewidth=2, label=f'$k = {k}$')
ax.set_xlabel('chi-square value')
ax.set_ylabel('density')
ax.set_title('Chi-squared distribution for various df')
ax.set_ylim(0, 0.5)
ax.legend()
ax.grid(alpha=0.3)
plt.tight_layout()
plt.show()
このグラフから、2つの特徴が読み取れます。まず、自由度 $k$ が小さいほど分布は左に寄り、右に長い裾を引いて強く歪みます。$k=1, 2$ では $x=0$ 付近に確率が集中しています。次に、$k$ が大きくなるにつれてピークが右へ移動し、形が左右対称な釣鐘型(正規分布)に近づいていきます。これは先ほどの「$k$ が大きいと正規近似できる」という性質の視覚的な裏付けです。

各曲線の点線は期待値 $k$ の位置を示しています。$k$ が大きくなるほどピークが期待値 $k$ の近くに来て対称に近づくこと、そして $k$ が小さいと分布が大きく右に歪むことが一目でわかります。検定でどの曲線を使うか(=自由度をいくつにするか)が結論を左右するので、自由度の決め方は後ほど丁寧に扱います。
ここまでで、ズレを測る物差し $\chi^2$ と、それを「珍しいかどうか」判定する基準分布が揃いました。いよいよ、この道具を使って具体的な検定を行います。最初は1つの分類軸を扱う適合度検定です。
適合度検定
設定と帰無仮説
適合度検定(goodness-of-fit test)は、「観測されたカテゴリ別の度数が、ある理論的な分布に従っているか」を判定する検定です。サイコロが公正か、ある月の交通事故が曜日に均等に分布しているか、遺伝の比が理論どおりか、といった「想定の分布への当てはまり具合」を調べます。
検定の出発点として、仮説を立てます。
- 帰無仮説 $H_0$: データは理論分布に従う(=ズレは偶然のゆらぎ)
- 対立仮説 $H_1$: データは理論分布に従わない(=ズレは本質的なもの)
仮説検定では、まず「差はない・偶然だ」とする帰無仮説 $H_0$ を仮に正しいと置き、その仮定のもとで観測されたようなズレ(あるいはそれ以上のズレ)がどれくらい起こりやすいかを評価します。起こりにくければ $H_0$ を棄却する、という背理法的な論理です。この枠組み自体は 統計的検定とは?仮説検定の手順と考え方をわかりやすく解説 で詳しく扱っています。
ここで注意したいのは、対立仮説が「従わない」という漠然とした主張になっている点です。カイ二乗検定は「どのカテゴリがどうズレているか」までは教えてくれません。あくまで「全体としてズレが大きすぎる」ことを検出する全体的な検定です。具体的にどのセルがズレの主因かを知りたければ、各カテゴリの寄与 $(O_i-E_i)^2/E_i$ を見たり、標準化残差 $(O_i-E_i)/\sqrt{E_i}$ を調べたりして、ズレの大きいセルを特定します。検定で「有意」が出た後に、この残差分析で原因を深掘りするのが定石です。
検定統計量は、すでに見たカイ二乗統計量です。
$$ \chi^2 = \sum_{i=1}^{k} \frac{(O_i – E_i)^2}{E_i} $$
$H_0$ が正しいとき、この統計量は近似的に自由度 $k-1$ のカイ二乗分布 $\chi^2(k-1)$ に従います。$k$ はカテゴリ数です。なぜ $k$ ではなく $k-1$ なのか、という自由度の話は次節で説明します。
具体例: サイコロの公正性
サイコロを120回振った結果が次のようになったとします。公正かどうかを検定しましょう。
| 目 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| 観測度数 $O_i$ | 15 | 23 | 18 | 21 | 24 | 19 |
| 期待度数 $E_i$ | 20 | 20 | 20 | 20 | 20 | 20 |
公正なサイコロなら各目が $120/6 = 20$ 回出ると期待されるので、$E_i = 20$ です。観測度数のズレを集計します。
$$ \chi^2 = \frac{(15-20)^2}{20} + \frac{(23-20)^2}{20} + \frac{(18-20)^2}{20} + \frac{(21-20)^2}{20} + \frac{(24-20)^2}{20} + \frac{(19-20)^2}{20} $$
分子を1つずつ計算すると $25, 9, 4, 1, 16, 1$ になります。これらをすべて足してから $20$ で割ります。
$$ \chi^2 = \frac{25 + 9 + 4 + 1 + 16 + 1}{20} = \frac{56}{20} = 2.8 $$

棒グラフを見ると、各目の観測度数(青)は期待度数20(赤い破線)の周りで凸凹していますが、極端に飛び抜けた目はありません。得られた $\chi^2 = 2.80$ がこの凸凹の総量を表します。問題は、この 2.80 が「公正なサイコロでも普通に出る範囲」なのか「不正のサイン」なのか、です。
自由度は $k – 1 = 6 – 1 = 5$ です。自由度5のカイ二乗分布で上側5%にあたる臨界値は $\chi^2_{0.05}(5) = 11.07$ です。観測した $2.8$ はこれよりずっと小さいので、帰無仮説を棄却できません。つまり「このサイコロは不正だ」と結論づける十分な証拠はない、ということになります。期待値が自由度に等しい(=5)ことを思い出すと、$\chi^2 = 2.8$ は平均より小さく、まったく驚くべき値ではないことが直感的にも分かります。
具体例で計算の流れは掴めましたが、まだ「なぜ自由度が $k-1$ なのか」という疑問が残っています。これは検定結果を大きく左右する重要な点なので、独立性の検定に進む前に整理しておきましょう。
自由度の決め方
自由度(degrees of freedom)は「データの中で自由に動かせる値の個数」を表します。直感的には、合計などの制約が課されると、その分だけ自由に決められる値が減る、と考えます。
適合度検定では、$k$ 個のカテゴリの度数を扱いますが、全体の合計 $N$ は固定されています(120回振ったなら、6つの目の度数の合計は必ず120)。すると、最初の $k-1$ 個の度数を自由に決めれば、最後の1個は「合計が $N$ になるように」自動的に決まってしまいます。自由に動けるのは $k-1$ 個なので、自由度は $k-1$ です。

左の図のように、6マスのうち合計 $N$ が固定されていると、5マスを自由に決めた時点で残り1マスは「決まる」ため、自由度は $6-1=5$ になります。右の図は独立性の検定の場合で、$r \times c$ の表で各行の合計と各列の合計が固定されると、自由に動かせるのは左上の $(r-1)\times(c-1)$ マスだけになり、残りは周辺度数から逆算で決まります。図のように青いマスだけが「自由」で、赤いマスは「決まる」のです。
このことから、独立性の検定(次節)の自由度は次のようになります。
$$ \text{自由度} = (r – 1)(c – 1) $$
ここで $r$ は行数、$c$ は列数です。一方、適合度検定で理論分布のパラメータをデータから推定した場合は、推定したパラメータの個数 $m$ だけさらに自由度が減り、$k – 1 – m$ になります(たとえば「ポアソン分布に従うか」を平均をデータから推定して検定する場合など)。本記事の例では理論比が最初から決まっているので、単純に $k-1$ です。
自由度がわかれば、使うべきカイ二乗分布の曲線が一意に定まります。これで適合度検定の道具立ては完成です。次は、2つの分類軸を同時に扱う独立性の検定に進みましょう。
独立性の検定
設定と期待度数の作り方
独立性の検定(test of independence)は、2つのカテゴリカル変数が独立か(無関係か)どうかを、分割表(クロス集計表)を使って判定します。「性別」と「商品の好み」、「治療法」と「回復の有無」のように、2軸でクロス集計したデータが対象です。
適合度検定との一番の違いは、期待度数 $E$ の作り方です。適合度検定では理論(公正なサイコロなら $1/6$ ずつ)から $E$ を決めましたが、独立性の検定では「もし2変数が独立だったら」という仮定のもとで、データそのものの周辺度数(行の合計・列の合計)から $E$ を計算します。
2つの変数が独立なら、セル $(i, j)$ に入る確率は「行 $i$ の確率」と「列 $j$ の確率」の積になります。確率論で言う独立性の定義 $P(A \cap B) = P(A)P(B)$ をそのまま分割表に当てはめたものです。行 $i$ に入る確率は $R_i/N$、列 $j$ に入る確率は $C_j/N$ なので、独立なら両者の積 $(R_i/N)(C_j/N)$ がセル $(i,j)$ の確率になります。これに全体数 $N$ をかけたものが期待度数です。
$$ E_{ij} = \frac{R_i \times C_j}{N} $$
ここで $R_i$ は第 $i$ 行の合計、$C_j$ は第 $j$ 列の合計、$N$ は全体の合計です。「独立なら、各セルは行と列の割合の掛け算で決まるはず」という素朴な期待を、そのまま式にしたものです。検定統計量は適合度検定と同じ形で、全セルにわたって和を取ります。
$$ \chi^2 = \sum_{i=1}^{r} \sum_{j=1}^{c} \frac{(O_{ij} – E_{ij})^2}{E_{ij}} $$
自由度は前節で見たとおり $(r-1)(c-1)$ です。
具体例: 性別と商品の好み
次の分割表で、性別と商品の好みに関連があるかを検定します。
| 商品A | 商品B | 商品C | 合計 | |
|---|---|---|---|---|
| 男性 | 30 | 20 | 50 | 100 |
| 女性 | 40 | 30 | 30 | 100 |
| 合計 | 70 | 50 | 80 | 200 |
まず期待度数を $E_{ij} = R_i C_j / N$ で計算します。男性・商品Aのセルなら、行計100・列計70・総数200なので $E_{11} = 100 \times 70 / 200 = 35$ です。同様に全セルを計算すると次のようになります。
| 商品A | 商品B | 商品C | |
|---|---|---|---|
| 男性 期待 | 35 | 25 | 40 |
| 女性 期待 | 35 | 25 | 40 |
男女とも合計100人ずつなので、独立を仮定した期待度数は男女で同じ値になります。

左が観測度数、右が「独立なら」の期待度数です。期待度数は青いセルだけでなく、行計・列計(グレーのセル)から機械的に作られている点を確認してください。観測と期待を見比べると、男性は商品Cが期待より多く(50 vs 40)、女性は商品Cが期待より少ない(30 vs 40)など、いくつかのセルでズレが目立ちます。このズレを集計します。
$$ \chi^2 = \frac{(30-35)^2}{35} + \frac{(20-25)^2}{25} + \frac{(50-40)^2}{40} + \frac{(40-35)^2}{35} + \frac{(30-25)^2}{25} + \frac{(30-40)^2}{40} $$
各項を計算すると $0.714, 1.0, 2.5, 0.714, 1.0, 2.5$ になります。商品Cの2項(各2.5)が大きく、ズレの主因であることがわかります。すべて足すと、
$$ \chi^2 = 0.714 + 1.0 + 2.5 + 0.714 + 1.0 + 2.5 = 8.43 $$
自由度は $(2-1)(3-1) = 2$ です。自由度2のカイ二乗分布で上側5%の臨界値は $\chi^2_{0.05}(2) = 5.99$ です。観測した $8.43$ はこれを上回るので、帰無仮説(性別と好みは独立)を棄却します。つまり、性別と商品の好みには関連があると言えます。とくに「男性は商品Cを好み、女性は商品Cを避ける」傾向がズレの主因だと、各項の内訳から読み取れました。
ここまでで2つの代表的な検定の手順が揃いました。しかし「臨界値を上回るかどうか」という判定は、もう一歩踏み込んで p 値で表現するのが現代的な作法です。次にその点を整理します。
p値・有意水準・棄却域の関係
検定の結論は、「観測した $\chi^2$ が、帰無仮説のもとでどれくらい起こりにくいか」を数値化することで下します。それが p値です。
p値は「帰無仮説が正しいと仮定したとき、観測された統計量と同じかそれ以上に極端な値が得られる確率」と定義されます。カイ二乗検定では、ズレが大きいほど $\chi^2$ が大きくなるので、p値は「観測した $\chi^2$ 値より右側(上側)の裾の面積」になります。
$$ p = P(\chi^2(k) \geq \chi^2_{\text{観測}}) $$
このp値を、あらかじめ決めた有意水準 $\alpha$(多くは0.05)と比べます。$p < \alpha$ なら「帰無仮説のもとではめったに起こらないことが起きた」と判断し、帰無仮説を棄却します。$p \geq \alpha$ なら棄却できません。これは「$\chi^2$ が臨界値(上側 $\alpha$ にあたる値)を超えるか」という判定と完全に同じことを、面積の言葉で言い換えたものです。

この図は自由度5のカイ二乗分布です。赤い破線が上側5%の臨界値(11.07)で、それより右の薄赤い領域が棄却域です。観測統計量(紫の縦線)より右の紫の領域がp値に対応します。観測統計量が臨界値より右にあれば、p値は5%を下回り、帰無仮説を棄却します。逆に観測統計量が臨界値より左なら、p値は5%を超え、棄却できません。「p値が小さい=ズレが大きい=裾の奥にある」という関係を、面積として目で捉えておくと検定の理解が安定します。
なお、カイ二乗検定では棄却域は分布の右側だけに取ります(片側)。これは、$\chi^2$ が小さいことは「データが期待によく合っている」ことを意味し、帰無仮説に不利な証拠にはならないからです。p値の詳しい解釈については p値の定義と正しい解釈をわかりやすく解説 も参照してください。
p値で結論が出せるようになりましたが、カイ二乗近似がきちんと成り立つには満たすべき前提があります。これを無視すると誤った結論を導きかねないので、次に注意点を確認します。
期待度数の条件とイェーツの連続性補正
期待度数は5以上が目安
カイ二乗統計量が「カイ二乗分布に従う」のは、あくまで近似です。この近似は、もともと離散的な度数を、連続なカイ二乗分布で近似することに由来します。各セルの期待度数が十分大きいときはこの近似が良く効きますが、期待度数が小さいセルがあると近似が崩れ、p値が信頼できなくなります。
経験則として、すべてのセルで期待度数が5以上であることが望まれます。より緩い基準では「期待度数5未満のセルが全体の20%以下、かつどのセルも1以上」とすることもあります。

左の図は、2×2の分割表でカイ二乗統計量の分布をシミュレートしたものです。標本サイズ $N=200$(青、期待度数が大きい)ではヒストグラムが理論曲線 $\chi^2(1)$(黒)によく一致していますが、$N=20$(赤、期待度数が5未満)では理論からのズレが見られます。期待度数が小さいとカイ二乗近似が信頼できなくなることが視覚的にわかります。
期待度数が5未満のセルがある場合の対処法は、おもに次の2つです。
- カテゴリを併合する: 隣り合うカテゴリをまとめて、各セルの度数を増やす
- フィッシャーの正確検定を使う: 近似に頼らず、超幾何分布から正確なp値を計算する手法。小標本に向きます
フィッシャーの正確検定やマクネマー検定については フィッシャーの正確検定とマクネマー検定 完全ガイド — 小標本・対応ありの分割表 で詳しく扱っています。
2×2表でのイェーツの連続性補正
とくに $2 \times 2$ の分割表(自由度1)は、離散から連続への近似が粗くなりやすく、$\chi^2$ を過大評価しがちです。これを補正するのがイェーツの連続性補正(Yates’ correction for continuity)です。各セルのズレの絶対値から0.5を引いてから二乗します。
$$ \chi^2_{\text{Yates}} = \sum \frac{(|O_{ij} – E_{ij}| – 0.5)^2}{E_{ij}} $$
右上の図は、ある $2 \times 2$ 表に対して補正なし(赤)とイェーツ補正あり(緑)で $\chi^2$ を比較したものです。補正によって統計量が $9.90$ から $7.27$ に下がり、p値が $0.002$ から $0.007$ へと大きくなっています。つまり補正は検定をやや保守的(棄却しにくく)にします。$|O-E|$ から0.5を引くことで、連続近似による過大評価を抑えているのです。scipy の chi2_contingency は $2 \times 2$ 表に対してデフォルトでこの補正を適用します。
近似の前提と補正を押さえれば、検定結果を安心して解釈できます。ただし、ここまでの議論には実務上の落とし穴がもう1つあります。それは「統計的に有意」と「効果が大きい」は別物だということです。次に効果量で補強します。
効果量 Cramér’s V — 有意性と効果の大きさは別
カイ二乗統計量には大きな弱点があります。それは、標本サイズ $N$ が大きいほど $\chi^2$ も大きくなるという性質です。式 $\chi^2=\sum(O-E)^2/E$ で、同じ「ズレの割合」を保ったまま $N$ を2倍にすると、$O$ も $E$ もほぼ2倍になり、$(O-E)^2$ は4倍、$/E$ で2倍に効くので、$\chi^2$ はおよそ2倍になります。
これは何を意味するでしょうか。十分に大きな標本を取れば、実質的にはごくわずかな関連でも「統計的に有意」になってしまうのです。「有意である」ことは「関連が強い」ことを保証しません。そこで、標本サイズの影響を取り除いて「関連の強さそのもの」を測る指標が効果量であり、分割表に対する代表的な効果量が Cramér’s V です。
$$ V = \sqrt{\frac{\chi^2}{N \cdot \min(r-1, c-1)}} $$
ここで $N$ は総度数、$\min(r-1, c-1)$ は行・列の自由度の小さいほうです。$\chi^2$ を $N$ で割ることで標本サイズの影響を打ち消し、$V$ は $N$ にほぼ依存しない値になります。$V$ は0から1の範囲を取り、0なら完全に独立、1に近いほど強い関連を意味します。目安として、自由度1のとき $V \approx 0.1$ で小、$0.3$ で中、$0.5$ で大の効果と解釈されることが多いです。

この図は、同じ偏りパターンを保ったまま標本サイズ $N$ を増やしたときの $\chi^2$(赤)と Cramér’s V(青)の変化です。$N$ が増えると $\chi^2$ は右肩上がりにどんどん大きくなり、いずれ必ず有意になります。一方で Cramér’s V はほぼ一定の値(約0.2)にとどまっています。これが「$\chi^2$ は標本サイズに引きずられるが、$V$ は関連の本質的な強さを捉える」という決定的な違いです。検定で有意が出たら、必ず効果量も併記して「どれくらい強い関連か」を伝えるのが望ましい作法です。効果量全般については 効果量(Cohen’s d・相関比・オッズ比)をわかりやすく解説 も参考になります。
理論はひととおり揃いました。最後に、これらをPythonでどう計算するかを、手計算との照合も含めて確認しましょう。
Pythonでの実装
適合度検定(scipy.stats.chisquare)
サイコロの例を、手計算と scipy.stats.chisquare の両方で計算し、結果が一致するか確認します。
import numpy as np
from scipy import stats
# サイコロの公正性の検定
observed = np.array([15, 23, 18, 21, 24, 19])
expected = np.array([20, 20, 20, 20, 20, 20])
# 手計算
chi2_manual = np.sum((observed - expected) ** 2 / expected)
df = len(observed) - 1
p_manual = 1 - stats.chi2.cdf(chi2_manual, df)
print(f"手計算: chi2 = {chi2_manual:.3f}, df = {df}, p = {p_manual:.4f}")
# SciPyによる検定
chi2_scipy, p_scipy = stats.chisquare(observed, expected)
print(f"SciPy : chi2 = {chi2_scipy:.3f}, p = {p_scipy:.4f}")
if p_scipy < 0.05:
print("結論: サイコロは公正でない可能性がある(有意水準5%)")
else:
print("結論: サイコロが不正であるという証拠は不十分")
実行すると、手計算と SciPy がともに $\chi^2 = 2.800$、$p = 0.7308$ を返し、完全に一致します。p値が0.73と非常に大きいので帰無仮説を棄却できず、「サイコロが不正だという証拠は不十分」という結論になります。chisquare の第2引数 expected を省略すると、全カテゴリが等確率と仮定して自動で期待度数を計算してくれるので、一様性の検定なら省略しても同じ結果が得られます。
独立性の検定(scipy.stats.chi2_contingency)
分割表の独立性の検定は chi2_contingency 一発で行えます。期待度数も自由度も自動で計算してくれます。
import numpy as np
from scipy import stats
# 分割表(性別 × 商品の好み)
observed = np.array([[30, 20, 50],
[40, 30, 30]])
chi2, p, dof, expected = stats.chi2_contingency(observed, correction=False)
print("観測度数:\n", observed)
print("\n期待度数:\n", np.round(expected, 1))
print(f"\nchi2 = {chi2:.3f}, 自由度 = {dof}, p値 = {p:.4f}")
# 効果量 Cramér's V も計算する
N = observed.sum()
k = min(observed.shape) - 1
cramers_v = np.sqrt(chi2 / (N * k))
print(f"Cramér's V = {cramers_v:.3f}")
if p < 0.05:
print("結論: 2変数は独立でない(関連がある)")
else:
print("結論: 2変数が独立でないとは言えない")
出力では、期待度数が手計算どおり男女とも [35, 25, 40] になり、$\chi^2 = 8.429$、自由度2、$p = 0.0148$ が得られます。p値が0.05を下回るので帰無仮説を棄却し、「性別と商品の好みには関連がある」と結論できます。さらに Cramér’s V は $0.205$ で、関連は「小〜中程度」とわかります。有意ではあるものの、関連の強さ自体は中くらい、という解釈です。ここで correction=False を指定しているのは、$2 \times 3$ 表ではイェーツ補正を使わないためです($2 \times 2$ 表ではデフォルトで補正が入る点に注意してください)。
実データ例: メンデルの遺伝の法則
最後に、適合度検定の歴史的な実データ例として、メンデルがエンドウ豆の交配で観測した形質の比を検定してみましょう。理論では2形質の組み合わせが $9:3:3:1$ になると予測されます。
import numpy as np
from scipy import stats
# メンデルの観測度数(丸・黄, しわ・黄, 丸・緑, しわ・緑)
observed = np.array([315, 108, 101, 32])
N = observed.sum()
# 理論比 9:3:3:1 からの期待度数
ratio = np.array([9, 3, 3, 1])
expected = N * ratio / ratio.sum()
chi2, p = stats.chisquare(observed, expected)
print(f"総数 N = {N}")
print(f"期待度数 = {np.round(expected, 2)}")
print(f"chi2 = {chi2:.3f}, df = {len(observed) - 1}, p = {p:.4f}")
if p < 0.05:
print("結論: 観測は 9:3:3:1 から有意にズレている")
else:
print("結論: 観測は 9:3:3:1 によく適合している")
実行すると期待度数は [312.75, 104.25, 104.25, 34.75]、$\chi^2 = 0.470$、自由度3、$p = 0.9254$ となります。p値が0.93と極めて大きく、観測データは理論比 $9:3:3:1$ に非常によく適合していることが確認できます。$\chi^2 = 0.47$ は自由度3の期待値(=3)よりもさらに小さく、観測が理論にぴったり合っていることを物語っています。これはまさに適合度検定が「データが理論分布に従っているか」を検証する典型例です。
シミュレーションで分布を確かめる
理論の締めくくりとして、「帰無仮説が正しいとき統計量が本当にカイ二乗分布に従うのか」をシミュレーションで確かめます。公正なサイコロを何度も振り直し、得られた $\chi^2$ のヒストグラムを描きます。
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
rng = np.random.default_rng(42)
n_sim, n_rolls = 20000, 120
chi2_values = np.empty(n_sim)
expected = np.full(6, n_rolls / 6)
for s in range(n_sim):
rolls = rng.integers(1, 7, n_rolls)
observed = np.bincount(rolls, minlength=7)[1:7]
chi2_values[s] = np.sum((observed - expected) ** 2 / expected)
fig, ax = plt.subplots(figsize=(9, 5))
ax.hist(chi2_values, bins=60, density=True, alpha=0.6, label='simulated')
x = np.linspace(0, 20, 300)
ax.plot(x, stats.chi2.pdf(x, 5), 'r-', linewidth=2, label='chi2(5) theory')
crit = stats.chi2.ppf(0.95, 5)
ax.axvline(crit, color='green', linestyle='--',
label=f'critical value = {crit:.2f}')
ax.set_xlabel('chi-square statistic')
ax.set_ylabel('density')
ax.legend()
ax.grid(alpha=0.3)
plt.tight_layout()
plt.show()
このシミュレーション結果を表したのが次の図です。

ヒストグラム(シミュレーション)が理論曲線 $\chi^2(5)$ にぴったり重なっています。帰無仮説(サイコロは公正)が正しいとき、検定統計量が確かに自由度5のカイ二乗分布に従うことが実験的に裏付けられました。緑の破線は臨界値(11.07)で、これより右に出た面積がちょうど全体の5%、つまり「公正なサイコロでも5%の確率で誤って棄却してしまう(第一種の誤り)」割合に対応します。検定の有意水準が何を意味するか、この図が直感的に教えてくれます。
まとめ
本記事では、カイ二乗検定の理論と使い方を、直感から実装まで一気通貫で解説しました。要点を振り返ります。
- カイ二乗統計量 $\chi^2 = \sum (O – E)^2 / E$ は、観測度数と期待度数のズレを期待度数で正規化して集計した「ズレの総量」を表す。
- カイ二乗分布は標準正規変数の二乗和が従う分布で、自由度 $k$ が小さいほど右に歪み、大きいと正規分布に近づく。期待値は $k$。
- 適合度検定は観測データが理論分布に従うかを検定し、自由度は $k-1$(推定パラメータがあればさらに減る)。
- 独立性の検定は分割表で2変数の独立性を検定し、期待度数は $E_{ij}=R_iC_j/N$、自由度は $(r-1)(c-1)$。
- p値は観測統計量より右側の裾の面積で、有意水準 $\alpha$ と比べて棄却を判断する。棄却域は右側のみ(片側)。
- 期待度数は5以上が近似の目安。$2 \times 2$ 表ではイェーツの連続性補正で過大評価を抑える。小標本ではフィッシャーの正確検定を使う。
- 効果量 Cramér’s V は標本サイズの影響を除いた関連の強さで、有意性とは別に必ず確認すべき。
カイ二乗検定は、より大きな「仮説検定」という枠組みの中の一つの道具です。連続量の平均を比べたいなら t検定や分散分析、対応のあるデータや小標本ならフィッシャー・マクネマー検定、というように、データの性質に応じて適切な検定を選ぶ眼を養うことが大切です。次のステップとして、以下の記事も参考にしてください。