「オッズ比」って何者?何がおいしいの?


統計の勉強をしていると、「オッズ」やら「オッズ比」やらといった単語に遭遇します。医療統計の分野なんかでよく用いられるようですが、直感的に何を表すものなのか分かりづらいように思います。こういったものが必要になる理論的な背景について気になったので、記事としてまとめてみました。

特にオッズ比とロジスティック回帰の関係性に焦点を当てていきます。KaggleのTitanicデータセットを使って、考察結果をPythonで確認してみたいと思います。

「オッズ比」とは何者か

まず定義から確認します。
「喫煙歴の有無」と「ガンの発症」の関連性を題材に考えます。

$n_1$人の「喫煙歴あり」グループと$n_2$人の「喫煙歴なし」グループがあったとしましょう。
それぞれのグループのガンの発症割合を$p_1, p_2$とすると、分割表 (contingency table) は次のようになります。

ガン発症 ガン未発症 合計
喫煙歴あり $n_1p_1$ $n_1(1-p_1)$ $n_1$
喫煙歴なし $n_2p_2$ $n_2(1-p_2)$ $n_2$
合計 $n_1p_1+n_2p_2$ $n_1(1-p_1)+n_2(1-p_2)$ $n_1+n_2$

このとき、それぞれのグループのガン発症のリスク (risk) は発症割合そのものです。すなわち「喫煙歴あり」グループのリスクは$p_1$, 「喫煙歴なし」グループのリスクは$p_2$となります。またこれらの比をとったものをリスク比 (RR : risk ratio) といいます。

$$RR=\frac{p_1}{p_2}$$

例えばリスク比の計算結果がRR=3であったとき、「『喫煙歴あり』グループは『喫煙歴なし』グループに比べてガン発症のリスクが3倍であった」と表現できます。非常に直感的で分かりやすい指標といえます。
ではオッズ (odds) は何なのかといえば、発症割合 (p) を未発症の割合 (1-p) で割ったものになります。

$$odds = \frac{p}{1-p}$$

そして異なる2群のオッズの比をとったものが、本記事のテーマである オッズ比 (OR : odds ratio) です。

$$OR = \frac{odd_1}{odds_2} = \frac{p_1/(1-p_1)}{p_2/(1-p_2)}$$

こちらはリスク比とは異なり、オッズ比が3であったからといって発症リスクが3倍であると表現することはできません。(「オッズ比が大きいほど発症リスクが高い」とは言えます)
このあたりを誤解して、オッズ比を用いて謝った解釈が与えられることがニュース記事なんかでもあるようです。

ではなぜ、オッズ比が実際の分析でよく使われるのでしょうか。

オッズ比が用いられる理由

オッズ比が用いられる理由として、以下のようなものが挙げられます。

  • 前向き研究と後ろ向き研究のどちらにも使える
  • pが小さい場合、リスク比の推定値として使える
  • ロジスティック回帰との相性が良い

一つずつみていきましょう。

【理由1】 前向き研究と後ろ向き研究のどちらにも使える

上記の問題設定を考える時、あらかじめ喫煙者$n_1$人と非喫煙者$n_2$人を集めてきて、一定期間経過後にそれらのうちの何人がガンを発症したかを調べる、というのが時系列に沿った自然な調査方法です。このようなタイプの研究デザインを前向き研究といいます。しかし実際には、ガンの発症のような稀な事象を観測するには$n_1, n_2$を相当大きくしなければならず、また対象の事象を観測するまでに時間がかかる、といった理由から前向き研究の実施が困難なケースがあります。

このような場合の代替的な手段として、実際にガンを「発症した人たち」と「発症していない人たち」をそれぞれ一定数集め、各人に喫煙歴が過去にあったかどうかを調べる、という方法が考えられます。前述の前向き研究に対し、こちらは後ろ向き研究と呼ばれます。ただし、知りたいのはあくまで前向き研究における$p_1, p_2$です。

ここで湧いてくる疑問が、「後ろ向き研究の結果得られたリスク比ないしオッズ比が、本来前向き研究でえるべきリスク比ないしオッズ比と本当に一致するのか?」というものです。結論から言えば、リスク比は一致しませんが、オッズ比は一致します。このことは、ベイズの定理を用いることで証明できます。
つまり、オッズ比には「後ろ向き研究から得られる観測データから、本当に知りたい前向き研究のオッズ比を推定できる」という便利な性質があり、これが分析の現場でよく用いられる理由の一つとなっています。

【理由2】 pが小さい場合、リスク比の推定値として使える

理由に書いた通りで、pが非常に小さい場合 (=関心のある事象が希少な場合)、$1-p \approx 1$と近似できるため、オッズ比は相対リスクの推定値として利用できます。

$$OR = \frac{p_1(1-p_1)}{p_2(1-p_2)} \approx\frac{p_1}{p_2} = RR$$

対象とする事象が希少な場合、後ろ向き研究のオッズ比が、リスク比の推定値としてそのまま利用できるわけです。

【理由3】 ロジスティック回帰モデルとの相性が良い

ロジスティック回帰モデルとは、ベルヌーイ分布に従う2値確率変数の統計回帰モデルです。確率変数Yが生起確率pのベルヌーイ分布に従うと仮定し、pをk個の説明変数$x_1, ..., x_k$で回帰させるとき、ロジスティック回帰モデルでは以下のような構造を仮定します。

$$log\frac{p}{1-p} = \beta_0+\beta_1x_1+...+\beta_kx_k$$

左辺は生起確率pをロジット変換 (logit transformation) したものです。すなわちロジスティック回帰モデルは、ロジット関数をリンク関数とする一般線形モデル (GLM) であると捉えることができます。
上式を変形すると以下のようになります。

$$\frac{p}{1-p} = exp(\beta_0+\beta_1x_1+...+\beta_kx_k) = e^\beta_0(e^\beta_1)^{x_1}...(e^\beta_k)^{x_k}$$

左辺はYのオッズそのものです。つまり上式は、$x_j$以外の説明変数を固定させたまま$x_j$の値を1増やすと、オッズが$e^{\beta_j}$倍になることを意味します。すなわち、$x_j$の値を1増やす前を基準として考えれば、$e^{\beta_j}$はオッズ比であることが分かります。オッズ比の対数をとったものを対数オッズ比 (log odds ratio) といい、これは回帰係数$\beta_j$に一致します。

$$log(OR) = log(e^{\beta_j}) = \beta_j$$

実際に一致するか確かめてみましょう。ここではKaggleのTitanicデータセットを使用します。

説明変数として性別 Sex のみを利用して乗客の生存 Survived {0, 1} を予測するロジスティック回帰モデルを考えます。

In
# ライブラリのインポート
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf

# データの読込み
df = pd.read_csv('data/titanic/train.csv')
# 性別データを数値に変換
df['Sex'] = df['Sex'].map({'male': 0, 'female': 1})

# ロジスティック回帰モデルをfitさせる
model_glm = smf.glm(
    formula = 'Survived ~ Sex', 
    data = df, 
    family = sm.families.Binomial()
).fit()

# 結果の出力
print(model_glm.summary())

以下のような出力が得られます。

Out
                 Generalized Linear Model Regression Results                  
==============================================================================
Dep. Variable:               Survived   No. Observations:                  891
Model:                            GLM   Df Residuals:                      889
Model Family:                Binomial   Df Model:                            1
Link Function:                  logit   Scale:                          1.0000
Method:                          IRLS   Log-Likelihood:                -458.90
Date:                Mon, 14 Dec 2020   Deviance:                       917.80
Time:                        16:24:17   Pearson chi2:                     891.
No. Iterations:                     4                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept     -1.4571      0.106    -13.701      0.000      -1.666      -1.249
Sex            2.5137      0.167     15.036      0.000       2.186       2.841
==============================================================================

説明変数 Sex の回帰係数 Coef は2.5137となっています。これが対数オッズ比と一致するかどうかを確認します。対数オッズ比は次のように計算されます。

In
df_f = df.query('Sex == 1')
df_m = df.query('Sex == 0')
print(len(df_f), len(df_m))
# 314 577

N_f_alive = len(df_f.query('Survived == 1'))
N_f_dead  = len(df_f.query('Survived == 0'))
N_m_alive = len(df_m.query('Survived == 1'))
N_m_dead  = len(df_m.query('Survived == 0'))
print(N_f_alive, N_f_dead, N_m_alive, N_m_dead)
# 233 81 109 468

odds1 = N_f_alive / N_f_dead
odds2 = N_m_alive / N_m_dead
log_odds_ratio = np.log(odds1 / odds2)
print(log_odds_ratio)
# 2.5137097125817647

出力結果の通り、回帰係数と対数オッズ比が一致することが確認できました。女性 (Sex == 1) の方がオッズが大きく、生存確率が高いことが分かります。(ただし生存確率が男性に比べて2.5倍であるということはできません)


以上、オッズ比とは何か、なぜ使われるのかについての解説でした!

参考