進階已經雙重審閱,尚未人工抽查

預測值與盛行率

PPV 與 NPV 是病人真正在問的問題,但它們不是檢驗的性質——同一個檢驗在不同盛行率下的 PPV 可以差兩個數量級。這一頁把 Bayes 的算式攤開、用人數講一次、示範為什麼罕見病篩檢的陽性多半是偽陽性,並且處理一個課本很少講的但書:敏感度與特異度的「不隨盛行率變」是關於算式的,不是關於世界的。

病人問的不是敏感度

門診裡沒有人會問「這個檢驗的敏感度是多少」。病人問的是:我的報告是陽性,那我到底有沒有病?

這個問題的答案是陽性預測值(positive predictive value, PPV),而它與敏感度是完全不同的量:

Sensitivity=P(檢驗陽性有病),PPV=P(有病檢驗陽性)\text{Sensitivity} = P(\text{檢驗陽性} \mid \text{有病}), \qquad \text{PPV} = P(\text{有病} \mid \text{檢驗陽性})

兩個條件機率的條件擺反了方向。把它們當成同一件事,是臨床上最常見也最貴的統計誤解——貴在它會讓一個罕見病的篩檢陽性被當成診斷,然後接上一整串侵入性檢查。

Bayes 把兩者接起來

2×2 表直接推:

PPV=sens×prevsens×prev+(1spec)×(1prev)\text{PPV} = \frac{\text{sens} \times \text{prev}}{\text{sens} \times \text{prev} + (1 - \text{spec}) \times (1 - \text{prev})} NPV=spec×(1prev)spec×(1prev)+(1sens)×prev\text{NPV} = \frac{\text{spec} \times (1 - \text{prev})}{\text{spec} \times (1 - \text{prev}) + (1 - \text{sens}) \times \text{prev}}

分子是「真陽性的比重」,分母是「所有陽性的比重」。盛行率 prev 出現在算式的兩邊,而敏感度與特異度裡沒有它。 這就是「預測值不是檢驗的性質」這句話的全部內容——不是玄學,是這條式子。

同一個檢驗,七種盛行率

沿用 2×2 表那一頁的設定:pROC::aSAH 的 S100β,切點 0.20 µg/L, 敏感度 63.4%、特異度 80.6%。把這兩個數字釘死,只動盛行率

盛行率(檢驗前機率)PPV陽性中的偽陽性比例NPV陰性中的偽陰性比例
0.1%0.3%99.7%99.95%0.05%
0.5%1.6%98.4%99.77%0.23%
1%3.2%96.8%99.54%0.46%
5%14.7%85.3%97.67%2.33%
10%26.6%73.4%95.20%4.80%
本研究世代65.0%35.0%79.45%20.55%
50%76.5%23.5%68.77%31.23%
曲線圖,橫軸是盛行率取對數,縱軸是預測值;PPV 曲線從左下往右上遞增,NPV 曲線從左上往右下遞減,另有一條虛線是敏感度與特異度都達到 99% 的檢驗的 PPV,垂直虛線標出本研究世代的盛行率。
敏感度與特異度全程固定不動,只有盛行率在移動。PPV 與 NPV 這兩條曲線就是上面那張表的連續版本;虛線是一個近乎完美的檢驗,它整條往左移了,但沒有改變形狀。產圖腳本 figures/scripts/B4-02-ppv-npv.R

盛行率 0.1% 時 PPV 是 0.3%,盛行率 50% 時是 76.5%—— 同一個檢驗、同樣的敏感度與特異度,PPV 差了超過兩個數量級。

值得記住的一個量是這個檢驗的打平盛行率:PPV 剛好到一半(也就是陽性報告讓「有病」與「沒病」勢均力敵)所需要的盛行率,這裡是 23.5%。低於這個盛行率,一張陽性報告最可能的解釋仍然是沒病

用人數講一次

機率會騙眼睛,人數不會。把 10000 個人送進這個檢驗,盛行率 0.1%:

真的有病(10 人)真的沒病(9990 人)合計
檢驗陽性6.31942.51948.8
檢驗陰性3.78047.58051.2

1948.8 張陽性報告裡,只有大約 6.3 個人真的有病。 其餘全部是偽陽性,PPV = 0.33%。

原因不在檢驗差,而在分母的大小差太多:沒病的人有 9990 位,就算只有 19.4% 被誤判,也會產生 1942.5 個偽陽性;而有病的人總共才 10 位,全部抓到也不過 10 個真陽性。偽陽性的數量由「沒病的人有多少」決定,真陽性的數量由「有病的人有多少」決定,而這兩個數字在罕見病裡差了好幾個數量級。

換一個近乎完美的檢驗也救不了

直覺的下一步是「那就用更好的檢驗」。把敏感度與特異度都拉到 99%,同樣送 10000 個人進來,盛行率一樣是 0.1%:

盛行率PPV(S100β 這個檢驗)PPV(99% / 99% 的檢驗)
0.1%0.3%9.0%
0.5%1.6%33.2%
1%3.2%50.0%
5%14.7%83.9%
10%26.6%91.7%
本研究世代65.0%98.3%
50%76.5%99.0%

在盛行率 0.1% 時,這個近乎完美的檢驗會產生 9.9 個真陽性與 99.9 個偽陽性, PPV 是 9.0%。十個陽性裡仍然只有一個是真的。 它的打平盛行率是 1.0%——比原本的 23.5% 好很多,但仍然遠高於這個疾病的盛行率。

NPV 的另一面:不要用高 NPV 說服自己

上面那張表裡 NPV 那一欄在低盛行率時看起來像是好消息:在盛行率 0.1% 時,NPV 是 99.95%。它其實幾乎沒有資訊:在盛行率 0.1% 的族群裡,就算完全不做檢驗、看到誰都說「你沒病」,也會有 99.9% 的正確率。 檢驗把它從 99.9% 推到 99.95%,改變非常有限。

判斷「這個檢驗結果到底改變了什麼」的正確工具,是把檢驗前機率與檢驗後機率並排比較,而不是單看檢驗後的絕對值。這件事有一個專門的量:概似比

一個課本很少講的但書

寫到這裡,最順的收尾方式是:「所以敏感度與特異度是檢驗的性質,PPV 與 NPV 是族群的性質,記住這句話就好。」

這句話對算式成立,對真實世界則是一個要檢查的假設。 把同一份資料依 WFNS 分級(入院時的神經學嚴重度)拆成兩層,兩層的盛行率差很多——而敏感度與特異度也跟著差很多

分層人數有病 n沒病 n盛行率敏感度(95% CI)特異度(95% CI)
WFNS 1-271145719.7%28.6%(11.7–54.6)94.7%(85.6–98.2)
WFNS 3-542271564.3%81.5%(63.3–91.8)26.7%(10.9–52.0)

嚴重度高的那一層,盛行率是 64.3%,敏感度 81.5%; 嚴重度低的那一層,盛行率 19.7%,敏感度只有 28.6%。 兩個敏感度的 95% 信賴區間完全不重疊,所以這個落差不太可能只是抽樣造成的。

動手跑一次

library(pROC)
data(aSAH, package = "pROC")

pos <- aSAH$s100b >= 0.20
dis <- aSAH$outcome == "Poor"
sens <- sum(pos & dis) / sum(dis)
spec <- sum(!pos & !dis) / sum(!dis)

ppv <- function(prev, sens, spec)
  sens * prev / (sens * prev + (1 - spec) * (1 - prev))
npv <- function(prev, sens, spec)
  spec * (1 - prev) / (spec * (1 - prev) + (1 - sens) * prev)

prev <- c(0.001, 0.005, 0.01, 0.05, 0.10, mean(dis), 0.50)
round(data.frame(prev,
                 PPV = ppv(prev, sens, spec),
                 NPV = npv(prev, sens, spec)), 4)

# 打平盛行率:PPV = 0.5 需要多高的檢驗前機率
(1 - spec) / (sens + 1 - spec)

# 用人數講一次
N <- 10000; p <- 0.001
c(TP = N * p * sens, FN = N * p * (1 - sens),
  FP = N * (1 - p) * (1 - spec), TN = N * (1 - p) * spec)

# 匯出給下面的 Python 用
write.csv(aSAH, "aSAH.csv", row.names = FALSE)

驗證環境:R 4.6.0 + pROC 1.19.0.1。這一節只用到基本運算,不需要額外套件。

常見誤用

誤用為什麼錯
把敏感度當成「陽性代表有病的機率」條件擺反了;後者是 PPV,還要吃進盛行率
引用某篇論文的 PPV 套到自己的病人PPV 綁定該研究的盛行率,換族群就不成立
從病例對照式取樣的資料直接算 PPV病例與對照的人數是研究者決定的,PPV 沒有意義
用高 NPV 說明「這個檢驗很會排除疾病」盛行率低時不做檢驗也有很高的 NPV,要看 LR−
認為「檢驗夠準就能解決罕見病篩檢」偽陽性數量由沒病者人數決定,敏感度再高也不變
把篩檢陽性當成診斷篩檢的作用是提高檢驗後機率到值得做確診檢查,不是終點
評估篩檢只算抓到幾個病人偽陽性帶來的侵入性檢查與過度診斷屬於成本欄
假設文獻的敏感度可以無條件搬到別的場域光譜效應:換族群會換掉病情組成,連敏感度都會動
用整體正確率評估罕見病的檢驗全部判陰性就有很高的正確率
在同一份資料上挑切點再報 PPV樂觀偏誤,見 切點選擇與兩條 ROC 的比較

重跑本頁的所有數字

/opt/homebrew/bin/Rscript figures/scripts/B4-02-ppv-npv.R

讀讀看這張圖

答案取自產生本頁圖表的同一份統計輸出,不是另外打上去的。

同一個檢驗、同樣的敏感度 0.634 與特異度 0.806,分別用在盛行率 0.1% 與 50% 的兩個族群上。PPV 會怎麼樣?

看答案與解析

正確答案: 在盛行率 0.1% 的族群裡 PPV 只有 0.0033,換到 50% 的族群就跳到七成六——PPV 綁在盛行率上

Bayes 的算式裡盛行率同時出現在分子與分母,而敏感度 0.634 與特異度 0.806 這兩個輸入裡沒有它——這就是「預測值不是檢驗的性質」的全部內容。盛行率 0.1% 時 PPV 是 0.0033,五成時是 0.7653,同一個檢驗差了兩個數量級。0.6500 是本研究世代量到的 PPV,它只在那個世代成立;把它搬到別的族群,等於把研究者收案的比例當成這位病人的檢驗前機率。

盛行率 0.1% 的一萬人送進這個檢驗(敏感度 0.634、特異度 0.806)。表上真陽性大約 6.3 位、偽陽性 1942.5 位。偽陽性為什麼這麼多?

看答案與解析

正確答案: 因為沒病的人有 9990.0 位,就算只有不到兩成被誤判,人數也遠多於全部的病人

偽陽性的數量等於沒病的人數乘上偽陽性率:9990.0 位沒病的人,特異度 0.806 代表將近兩成會被誤判,於是產生 1942.5 個偽陽性。有病的人總共才 10.0 位,全部抓到也只有十個真陽性,實際抓到 6.3 位。被漏掉的病人是偽陰性,落在陰性那一格,不會變成偽陽性——那是把兩個錯誤格搞混。8047.5 是真陰性,它多不多與偽陽性的絕對數沒有關係。這就是罕見病篩檢的結構:兩個分母差了好幾個數量級。

把敏感度與特異度都拉到 99%,在盛行率 0.1% 的族群再跑一次。陽性報告現在可以當成診斷了嗎?

看答案與解析

正確答案: 不行。PPV 只升到 0.0902,十張陽性報告裡仍然只有一張是真的

換一個更好的檢驗只把偽陽性壓小,沒有改變兩個分母的比例,所以 PPV 只升到 0.0902,十張陽性裡仍有九張是假的。打平盛行率 0.0100 是「PPV 剛好到一半」所需要的檢驗前機率,它比這個族群的盛行率高了一個數量級——低於打平盛行率,一張陽性報告最可能的解釋仍然是沒病。0.9900 只是這個檢驗在病例與非病例對半分的族群裡的 PPV,不是它的固有性質。要提高 PPV,最有效的槓桿通常不是換檢驗,是把受檢對象縮小到檢驗前機率較高的人。

在盛行率 0.1% 的族群裡,這個檢驗的 NPV 是 99.95%。這個數字說明它很會排除疾病嗎?

看答案與解析

正確答案: 說明不了。陰性報告裡的偽陰性比例是 0.0005,而在這個族群裡不做檢驗、看到誰都說沒病,答錯的比例也只有千分之一

NPV 的高低主要由這個族群裡本來就沒病的人佔多少決定。盛行率 0.1% 時,完全不做檢驗、對每個人都說沒病,答錯的比例已經只有千分之一;檢驗把陰性報告的偽陰性比例壓到 0.0005,改變非常有限。0.9995 是檢驗後的絕對值,單看它會把「這個族群本來就很健康」誤讀成「這個檢驗很強」。0.6877 確實是同一個檢驗在對半分族群裡的 NPV,但那不是運氣——那就是盛行率在算式裡的位置。判斷檢驗改變了什麼,要把檢驗前與檢驗後並排比較,而那個量是概似比。

把同一批病人依 WFNS 分級拆成兩層,敏感度一層是 0.286、另一層是 0.815。這與「敏感度不隨盛行率變」矛盾嗎?

看答案與解析

正確答案: 不矛盾。兩層是兩群不同的病人:重症那一層的敏感度較高,而它的特異度掉到 0.267,兩個指標一起被病情組成推動

前一頁的示範是把同一批人整批複製,沒有換人,所以敏感度紋風不動——那是算式的性質。這裡換掉的是病人本身:WFNS 較高那一層腦損傷更重、標記濃度也更高,同一個切點抓得住他們,敏感度升到 0.815;同樣的機制讓那一層連結果好的人也偏高,於是更常跨過切點成為偽陽性,特異度掉到 0.267。兩個指標一起被病情組成推動,這叫光譜效應。0.546 是輕症那一層敏感度的區間上界,而重症那一層的下界比它高,兩個區間其實沒有重疊。0.643 是重症那一層的盛行率,它與敏感度一起改變,但不是敏感度改變的原因。

這個檢驗的打平盛行率是 23.5%。臨床上該怎麼用這個數字?

看答案與解析

正確答案: 檢驗前機率低於 0.2347 時,一張陽性報告最可能的解釋仍然是沒病

打平盛行率是 PPV 剛好到一半所需要的檢驗前機率:低於 0.2347,陽性報告讓有病與沒病的勝算仍然偏向沒病那一邊。這不等於陽性報告沒有意義——它確實把機率往上推了,只是還沒推過一半,後面通常還要接確診檢查。0.3500 是本研究世代裡陽性報告中偽陽性的比例,不是門檻。0.0100 是那個近乎完美的檢驗的打平盛行率,把它當成本檢驗的門檻,等於把一個做不到的標準記在錯的檢驗頭上。

延伸觀看

Sensitivity, Specificity, PPV, NPV
ENDirty Medicine· 11 min四個指標一次講完,重點放在 PPV / NPV 怎麼被盛行率牽著走,正好是本頁第三節。
Sensitivity and Specificity Explained Clearly (Biostatistics)
ENMedCram· 12 min用臨床情境把四個指標串起來,適合在讀完本頁第二節的算式後補直覺。
醫學統計 EP17 敏感度、特異度與預測值
繁中EDMAN MURMURS· 9 min繁中,預測值的中文說法在這裡有對照。
實證醫學-診斷與篩檢
繁中rookie days 菜鳥日子· 31 min繁中,把篩檢與診斷兩種情境的差別講得比多數教科書清楚,對應本頁第五節。
Principles of Epidemiology 10. Diagnosis, Tests, and Screening
繁中臺大開放式課程 NTU OCW· 60 min繁中完整課程。篩檢計畫的流行病學脈絡(包含 lead time 與 length bias)在這裡。

素材來源與授權

本頁為原創內容

回報內容問題

這個站的統計內容由 AI 撰寫、AI 互審,人工只做抽查。你看得出來的錯,我們不一定看得出來。

寫得越具體越修得動,例如哪一句話跟哪本教科書/哪篇論文的說法不一致。

留了才回得了信;不留也會看。

一併送出的資訊

這些是自動帶上的,每一項都可以取消。