概似比與 Fagan nomogram
LR 把一個檢驗結果變成「檢驗前勝算要乘上多少」,因此它不隨盛行率改變,卻又能直接算出這位病人的檢驗後機率。這一頁講 LR+ 與 LR− 怎麼來、Fagan nomogram 怎麼看、為什麼多階層 LR 比二分好用——以及在這份資料上,最低兩段的 LR 分不開,這份資料不足以分辨它們是否不同。
這個量在解決什麼問題
前兩頁留下一個實務上的僵局:
- 敏感度與特異度是檢驗的性質,可以從文獻搬過來用,但它們回答的是「有病的人會怎樣」,不是病人問的問題。
- PPV 與 NPV 回答了病人的問題,但它們綁死在該研究的盛行率上,換一群病人就不能用。
概似比(likelihood ratio, LR)是把兩者接起來的那個量。它有兩個性質同時成立,而這在診斷準確度的家族裡是唯一的:
- 它由敏感度與特異度算出來,所以跟它們一樣不隨盛行率改變,可以從文獻搬過來。
- 它可以直接把「這位病人的檢驗前機率」換算成「檢驗後機率」,所以能回答病人的問題。
代價是要換一個尺度想事情:勝算(odds)而不是機率。
定義
分子是「有病的人出現這個結果的機率」,分母是「沒病的人出現同一個結果的機率」。所以 LR 讀作:看到這個結果,比較支持哪一邊,支持多少倍。
它的用法是一行乘法(Bayes 定理寫成勝算形式):
機率與勝算的互換是 與 。整個流程是三步:機率換勝算 → 乘 LR → 勝算換回機率。
這一頁的數字
沿用 pROC::aSAH 的 S100β,切點 0.20 µg/L:敏感度 63.4%、特異度 80.6%。
| 算式 | 估計值 | 95% CI | |
|---|---|---|---|
| LR+ | 63.4% / (1 − 80.6%) | 3.26 | 1.93–5.51 |
| LR− | (1 − 63.4%) / 80.6% | 0.454 | 0.299–0.690 |
信賴區間用的是 Simel 的方法(在 log 尺度上算再取回來),因為 LR 是比值,它的抽樣分布在原尺度上是偏斜的。 LR 的區間要看它有沒有跨過 1:跨過 1 表示這個結果沒有明顯偏向任何一邊。這裡兩個區間都沒跨過 1。
Fagan nomogram
Fagan nomogram 是上面那三步乘法的圖形版:左邊軸找到檢驗前機率、中間軸找到 LR、把兩點連成一條直線並延長到右邊軸,交點就是檢驗後機率。
(它跟預測模型論文裡那種 nomogram 不是同一個東西:那一種是把一個已經配好的迴歸模型的線性預測值換算成分數,讀法是每條軸垂直往上讀分數、相加,不是拿尺連一條斜線。兩者的差別整理在nomogram 那一頁。)
figures/scripts/B4-03-likelihood-ratio.R用本研究世代的盛行率 36.3% 當檢驗前機率:
| 檢驗前機率 | 陽性 → 檢驗後機率 | 陰性 → 檢驗後機率 | 陽性帶來的絕對變化 |
|---|---|---|---|
| 5.0% | 14.7% | 2.3% | +9.7 個百分點 |
| 10.0% | 26.6% | 4.8% | +16.6 個百分點 |
| 20.0% | 44.9% | 10.2% | +24.9 個百分點 |
| 36.3% | 65.0% | 20.5% | +28.7 個百分點 |
| 50.0% | 76.5% | 31.2% | +26.5 個百分點 |
| 70.0% | 88.4% | 51.4% | +18.4 個百分點 |
這張表有一個容易被忽略的規律:同一個 LR 在不同的檢驗前機率下,帶來的絕對變化不一樣,而且在中間最大。 檢驗前機率 5% 時陽性只推高 9.7 個百分點,36.3% 時推高 28.7 個百分點, 到了 70% 又縮回 18.4 個百分點。
臨床推論很直接:對於已經幾乎確定有病、或幾乎確定沒病的病人,再多做一個中等強度的檢驗改變不了處置。 檢驗的價值集中在「不確定」的那一段,這也是決策曲線分析(decision curve analysis)那一整套方法要處理的問題。
LR 不隨盛行率改變——同樣用資料看
跟2×2 表那一頁一樣的做法:把病例或對照整批複製,改變世代的盛行率,再算一次。
| 病例 : 對照的複製比 | 盛行率 | PPV | LR+ | LR− |
|---|---|---|---|---|
| 1:4 | 12.5% | 31.7% | 3.261 | 0.454 |
| 1:1 | 36.3% | 65.0% | 3.261 | 0.454 |
| 4:1 | 69.5% | 88.1% | 3.261 | 0.454 |
PPV 從 31.7% 走到 88.1%,LR 兩欄一位小數都沒動。這就是為什麼 meta-analysis 合併診斷準確度時,合併的對象是敏感度/特異度或 LR,而不是 PPV。
(但上一頁最後那個但書同樣適用:換到病情組成不同的族群,LR 也會跟著動,因為敏感度與特異度會動。「不隨盛行率變」指的是算式,不是保證跨場域通用。)
多階層 LR:不要把連續值壓成兩格
把一個連續的檢驗值二分成陽性/陰性,會丟掉資訊:S100β 剛好在切點上方一點點的人,跟高出十倍的人,被當成同一件事。
多階層 LR(multilevel likelihood ratio)的做法是切成幾段,每一段各自算自己的 LR:某一段的 LR = 有病者落在這段的比例 ÷ 沒病者落在這段的比例。
| S100β(µg/L) | 結果差的人數(佔比) | 結果好的人數(佔比) | LR | 95% CI | 檢驗後機率 |
|---|---|---|---|---|---|
| < 0.10 | 7(17.1%) | 28(38.9%) | 0.439 | 0.211–0.915 | 20.0% |
| 0.10-0.19 | 8(19.5%) | 30(41.7%) | 0.468 | 0.237–0.924 | 21.1% |
| 0.20-0.39 | 9(22.0%) | 6(8.3%) | 2.634 | 1.009–6.874 | 60.0% |
| >= 0.40 | 17(41.5%) | 8(11.1%) | 3.732 | 1.767–7.882 | 68.0% |
最後一欄的檢驗後機率都從同一個檢驗前機率(36.3%)出發。落在最高一段的病人被推到 68.0%, 落在最低一段的被拉到 20.0%——而二分法會把最低兩段的病人全部歸成同一個「陰性」,把最高兩段全部歸成同一個「陽性」。
figures/scripts/B4-03-likelihood-ratio.R動手跑一次
library(pROC)
data(aSAH, package = "pROC")
pos <- aSAH$s100b >= 0.20
dis <- aSAH$outcome == "Poor"
tp <- sum(pos & dis); fp <- sum(pos & !dis)
fn <- sum(!pos & dis); tn <- sum(!pos & !dis)
sens <- tp / (tp + fn); spec <- tn / (tn + fp)
lr_pos <- sens / (1 - spec)
se <- sqrt(1/tp - 1/(tp + fn) + 1/fp - 1/(fp + tn)) # Simel
exp(log(lr_pos) + c(0, -1.96, 1.96) * se)
# 三步走:機率 -> 勝算 -> 乘 LR -> 換回機率
post <- function(pre, lr) { o <- pre / (1 - pre) * lr; o / (1 + o) }
post(0.20, lr_pos)
# 多階層 LR:每一段各自跟「有病 / 沒病的分布」比
band <- cut(aSAH$s100b, c(0, 0.10, 0.20, 0.40, Inf), right = FALSE)
tab <- table(band, dis)
(tab[, "TRUE"] / sum(dis)) / (tab[, "FALSE"] / sum(!dis))
# 匯出給下面的 Python 用
write.csv(aSAH, "aSAH.csv", row.names = FALSE)驗證環境:R 4.6.0 + pROC 1.19.0.1。LR 的信賴區間用 Simel 的 log 尺度公式,自己寫三行就好,不需要額外套件。
import numpy as np
import pandas as pd
d = pd.read_csv("aSAH.csv") # 由本頁上面那段 R 匯出
pos = d["s100b"] >= 0.20
dis = d["outcome"] == "Poor"
tp = (pos & dis).sum(); fp = (pos & ~dis).sum()
fn = (~pos & dis).sum(); tn = (~pos & ~dis).sum()
sens, spec = tp / (tp + fn), tn / (tn + fp)
lr_pos, lr_neg = sens / (1 - spec), (1 - sens) / spec
se = np.sqrt(1/tp - 1/(tp + fn) + 1/fp - 1/(fp + tn))
print(np.exp(np.log(lr_pos) + np.array([0, -1.96, 1.96]) * se))
def post(pre, lr):
o = pre / (1 - pre) * lr
return o / (1 + o)
band = pd.cut(d["s100b"], [0, 0.10, 0.20, 0.40, np.inf], right=False)
tab = pd.crosstab(band, dis)
print((tab[True] / dis.sum()) / (tab[False] / (~dis).sum()))Python 沒有標準的 LR 函式,直接照定義寫;重點是 CI 要在 log 尺度上算再取回來。
常見誤用
| 誤用 | 為什麼錯 |
|---|---|
| 把 LR 當成機率報告 | LR 是勝算要乘的倍數,本身不是機率,可以大於 1 |
| 在機率尺度上直接乘 LR | 必須先換成勝算;機率直接相乘沒有意義 |
| 用族群盛行率當每一位病人的檢驗前機率 | 檢驗前機率是這位病人的,要納入症狀、病史、風險因子 |
| 把多個檢驗的 LR 直接連乘 | 需要各檢驗結果在疾病狀態下條件獨立,臨床上常不成立 |
| 報 LR 不報信賴區間 | LR 是比值,區間偏斜且常常很寬;跨過 1 表示這個結果沒有明顯偏向 |
| 只憑 LR 的大小判斷檢驗有沒有用 | 要看檢驗後機率有沒有跨過決策門檻,門檻由後果決定 |
| 把 LR 分級門檻當成硬規定 | 那是經驗法則;同一個 LR 在不同檢驗前機率下的作用差很多 |
| 為了表格好看而多切幾層 | 每層人數變少、CI 變寬;相鄰層 LR 沒分開就該合併 |
| 分層界線從資料挑出來卻不說 | 與挑切點同一個問題,會產生樂觀偏誤 |
| 對幾乎確定或幾乎排除的病人再加做中等強度檢驗 | 絕對變化在極端的檢驗前機率下很小,改變不了處置 |
重跑本頁的所有數字
/opt/homebrew/bin/Rscript figures/scripts/B4-03-likelihood-ratio.R讀讀看這張圖
答案取自產生本頁圖表的同一份統計輸出,不是另外打上去的。
這個檢驗的 LR+ 是 3.26。一位檢驗前機率 0.20 的病人拿到陽性報告,檢驗後機率該怎麼算?
看答案與解析
正確答案: 先把 0.20 換成勝算,乘上 LR+ 之後再換回機率,得到 0.449
LR 乘在勝算上,不是乘在機率上。檢驗前機率 0.20 對應的勝算是四分之一,乘上 3.261 之後再換回機率,得到 0.449。把 0.20 直接乘 3.261 會得到大於二分之一的數,而且在檢驗前機率較高時會超過一,一看就知道尺度錯了。0.102 是同一位病人拿到陰性報告時的檢驗後機率——同一列裡相鄰的兩欄,方向完全相反。整個流程固定是三步:機率換勝算、乘 LR、勝算換回機率。
LR+ 是 3.26,95% 信賴區間 1.93 到 5.51。要判斷這個陽性結果有沒有偏向某一邊,該看區間的什麼?
看答案與解析
正確答案: 看下界 1.93 有沒有大於 1——它大於 1,所以這個結果確實偏向有病
LR 是比值,它的無資訊點是 1 而不是 0:LR 等於 1 表示有病與沒病的人出現這個結果的機率一樣。所以要看的是區間有沒有跨過 1,這裡下界 1.93 已經大於 1。5.51 是上界,拿它去對照常被引用的分級門檻,等於把最樂觀的一端當成估計值。0.69 是 LR− 的上界,它回答的是陰性結果的問題,與這一題無關;兩欄各有各的區間,不必也不會一起跨線。
同一個 LR+ 3.26 用在三位病人身上,檢驗前機率分別是 0.05、0.36 與 0.70。哪一位因為這張陽性報告改變最多?
看答案與解析
正確答案: 檢驗前機率 0.36 那位,絕對變化 0.287——同一個 LR 的絕對效果在中段最大
乘法發生在勝算尺度上,換回機率時會被壓在零與一之間,所以同一個 LR 在兩端的絕對變化都小、中段最大。0.36 那位增加 0.287 個機率單位,0.70 那位只增加 0.184,0.05 那位增加 0.097。注意這與 LR 的大小無關,三位病人用的是同一個 3.26。臨床推論很直接:對已經幾乎確定有病或幾乎確定沒病的人,再加做一個中等強度的檢驗改變不了處置,檢驗的價值集中在不確定的那一段。
把病例或對照整批複製,世代盛行率從 12.5% 換到 69.5%,再算一次 PPV 與 LR。哪一個說法對?
看答案與解析
正確答案: PPV 從三成一走到八成八,LR+ 在三個世代都是 3.261,一位小數都沒動
LR+ 是敏感度除以一減特異度,兩個輸入都在各自的疾病狀態內部算,複製整批人不會動到它們,所以 LR+ 在三個世代都是 3.261。PPV 則混了兩群人,從 0.317 走到 0.881。這正是診斷準確度的 meta-analysis 合併敏感度、特異度或 LR、而不合併 PPV 的理由——各研究的盛行率不同,PPV 之間不可比。但「不隨盛行率變」講的是算式:換到病情組成不同的族群時,敏感度與特異度本身會動,LR 也就跟著動。
多階層 LR 把這個標記切成四段。最低兩段的 LR 是 0.439 與 0.468,兩段的 95% 信賴區間幾乎完全重疊。正確的說法是什麼?
看答案與解析
正確答案: 最低那一段的區間從 0.211 一路到 0.915,這份資料不足以分辨兩段的 LR 是否不同
未達到可分辨不等於相同。兩段的區間都很寬——最低那一段從 0.211 一路到 0.915——而且幾乎完全重疊,能說的只有「這份資料不足以分辨它們是否不同」。把 0.468 與 0.439 當成同一個數,是把沒有證據當成沒有差異。第三段的 2.634 反而是真正拉開的地方:它與最高段的 3.732 一起被二分法平均掉,那才是二分法丟掉的東西。切愈多層每層人愈少、區間愈寬,所以分層界線要事先依臨床意義決定,切完再檢查相鄰兩層有沒有真的分開。
四個區間的檢驗後機率都從同一個檢驗前機率 36.3% 出發。最高那一段被推到 0.680,最低那一段被拉到 0.200。二分法會怎麼處理這四段?
看答案與解析
正確答案: 二分法把最高兩段併成一個「陽性」,於是原本檢驗後機率 0.680 與 0.600 的兩群人拿到同一個數
二分法只有陽性與陰性兩個結果,所以最高兩段的病人一起變成陽性、最低兩段一起變成陰性。原本檢驗後機率 0.680 與 0.600 的兩群人被壓成同一個數,0.200 與 0.211 那兩群也是。二分法用的 LR+ 是那兩段合起來算出來的,不是最高那一段的 3.732——把它當成整體的 LR+ 會系統性高估中度升高的那一群。這正是多階層 LR 想救回來的資訊:剛好落在切點上方一點點的人,跟高出十倍的人,被當成同一件事。
用到這個方法的章節
延伸觀看
What Are Likelihood Ratios and How Are They Used
Likelihood Ratios Explained
Likelihood Ratios and The Probability of Diagnosis
Diagnosis 03: Likelihood Ratios
好想告訴你的醫學統計-敏感性、特異性、陽性預測值與陽性概似比素材來源與授權
本頁為原創內容