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

連續變項要不要切成分組

切成四分位會損失多少檢定力、為什麼有時候切完反而更顯著(那不是好消息)、「最佳切點」搜出來的效果量為什麼一定偏大、P for trend 把 1/2/3/4 當數值時假設了什麼,以及有些變項根本切不出四分位。

這個決定每天都在發生

年齡切成「≥ 65 歲」、BMI 切成四類、CRP 切成「高/低」、腫瘤標記切成四分位—— 臨床論文裡到處都是。理由通常是「這樣比較好講」「臨床上就是這樣分的」「reviewer 要求」。

方法學文獻對這件事的立場一面倒:不要切。但那個立場是有前提的,而前提常常沒被講出來。 這一頁用兩份資料把前提找出來——因為它們剛好落在相反的兩邊。

兩份資料,兩個方向

資料 / 變項結果模型非線性檢定
A. MASS::birthwtlwt(產婦體重,磅)189 人,低出生體重 59 例logisticχ² 2.49,df 3,p 0.478
B. survival::rotterdampgr(黃體素受體,fmol/l)2982 人,復發或死亡 1713 例Coxχ² 9.45,df 3,p 0.024

A 的樣條沒有偵測到偏離直線;B 偵測到了。這一個差別會把後面所有結果的方向反過來。

library(MASS); library(survival); library(splines)
data(birthwt, package = "MASS")

bw <- birthwt
bw$race_f <- factor(bw$race, levels = 1:3, labels = c("White", "Black", "Other"))

# 1. 保留連續
glm(low ~ lwt + smoke + race_f, data = bw, family = binomial)

# 2. 切成四分位,最低的一組當參考組
bw$lwt_q <- cut(bw$lwt, quantile(bw$lwt, 0:4/4), include.lowest = TRUE)
glm(low ~ lwt_q + smoke + race_f, data = bw, family = binomial)

# 3. P for trend:把 1/2/3/4 當成一個數值變項
bw$lwt_q_num <- as.integer(bw$lwt_q)
glm(low ~ lwt_q_num + smoke + race_f, data = bw, family = binomial)

# 4. 樣條:不用線性假設,也不用切
sp <- ns(bw$lwt, knots = quantile(bw$lwt, c(.25, .5, .75)),
         Boundary.knots = quantile(bw$lwt, c(.05, .95)))
glm(low ~ sp + smoke + race_f, data = bw, family = binomial)

驗證環境:R 4.6.0 + MASS 7.3.65 + survival 3.8.6。cut() 的 include.lowest = TRUE 不能省,否則最小值會變成 NA。

方向 A:線性大致成立時,切組就是純虧

lwt 是產婦最後一次月經時的體重(磅),結果是新生兒低出生體重, 模型另外校正抽菸與族裔。三種做法的同一個關聯:

做法報出來的效果量zpAIC
保留連續(每 10 磅)OR 0.876-2.100.036225.01
四分位(Q4 vs Q1)OR 0.412(0.16–1.04)-1.880.060227.27
P for trend每上升一個四分位 OR 0.768-1.740.082226.88

同一份資料、同一個關聯:保留連續時達到統計顯著;切成四分位之後未達; P for trend 也未達。z|z| 從 2.10 掉到 1.88 再到 1.74, 而切組的兩個版本 AIC(227.27 與 226.88)都比連續版本的 225.01 高。

四個組的細節在這裡,順便看一件事:

四分位體重範圍(磅,含上界)n事件OR95% CIp
Q180–11053251(參考)
Q2110–12143100.3340.13–0.850.021
Q3121–14046120.4860.20–1.190.113
Q4140–25047120.4120.16–1.040.060

點估計不是單調的。 最低的是 Q2(OR 0.334), Q3 又回升到 0.486。

但不要把這個起伏歸給「切組製造的雜訊」。 同一份資料的樣條擺的是同一個形狀: 從 94 磅一路下降到約 125 磅的谷底 (0.456),在約 150 磅回升到 0.658, 之後才再往下。連續與切組兩種做法看到的是同一個上上下下。

能說的只有這句:非線性檢定未偵測到偏離直線 (χ² 2.49、df 3、 p 0.478),而信賴區間寬到分不出「真的有起伏」與「其實是一條直線」。 在這種情況下選線性項,是因為它比較省參數,不是因為已經證明關係是直線。

而 P for trend 正是假設它單調而且等距的(下一節)。

方向 B:切完變強,代表線性假設本來就錯了

pgr 是乳癌組織的黃體素受體濃度,右偏得很厲害:中位數 41、 平均 162、最大值 5004 fmol/l。 結果是 recurrence-free survival,模型校正腫瘤大小與停經狀態。

做法報出來的效果量zpAIC
保留連續(每 100 fmol/l)HR 0.979-2.250.02425393.55
四分位(Q4 vs Q1)HR 0.812(0.71–0.93)-2.950.00325388.96
P for trend每上升一個四分位 HR 0.934-3.140.00225389.16
樣條(3 個內部 knot)見圖 B25390.10

方向整個反過來:z|z| 從 2.25 上升到 2.95,再到 3.14。 如果只看這一份資料,很容易得出「切組比較敏感」的結論。

它其實在告訴你別的事。 線性模型在這裡本來就配不上資料: 樣條 vs 線性的非線性檢定 χ² 9.45、 df 3、p 0.024。

先講清楚真實的形狀,因為它跟直覺不一樣:低值區本來就是平的—— 從 0 到約 63 fmol/l,樣條貼在 1 附近,在 23 fmol/l 處還微升到 1.053;下降主要發生在約 23 到 491 fmol/l 之間, 之後轉平。所以問題不是「線性模型在低值區的斜率不夠陡」。

問題是一條直線被要求同時服務 0 到 5004 fmol/l 的整個全距

  • 一半的病人擠在 0 到 41 fmol/l (中位數就是 41,四分位切點是 0 / 4 / 41 / 198)。 在這一段直線幾乎分不開任何人——連跨過整個四分位距 (4 到 198 fmol/l), 線性模型也只給 HR 0.960。
  • 而斜率是被右尾少數幾個極高值的人定下來的:他們離其他人最遠, 對一個單一線性係數的影響也最大。

於是同一個係數必須同時代表「0 與 41 之間」與 「198 與 5004 之間」, 而樣條顯示這兩段的形狀根本不同。切成四分位至少把最高的四分之一單獨切出來、 讓它自己有一個估計,所以「看起來」變強了。

AIC 也指向同一件事:線性 25393.55 是三者中最差的, 四分位 25388.96 與樣條 25390.10 都比它低。 四分位與樣條之間只差 1.15——這個差距太小, 不足以拿來選模型。選樣條的理由不是 AIC,是它不需要憑空決定三個切點、 不把組內的變異當成沒發生過,而且畫得出一條可以讀的曲線。

兩個並排的面板,各自把同一個變項的三種模型畫在同一組座標上,縱軸都是相對於最低四分位中位數的效果量、取對數刻度,水平虛線畫在 1。左邊的面板標題為「Non-linearity not detected」,橫軸是產婦體重 94 到 188 磅:紅色虛線(線性模型)是一條平緩下降的直線,藍色實線(樣條)在它兩側來回擺動並數次與它交叉,最大落差出現在 120 磅附近,但淡藍色的信賴區間帶很寬,整段都把紅線包在裡面;綠色的階梯是四分位模型,每一階橫跨該組的範圍,菱形點畫在各組中位數處並帶有 95% 信賴區間的直立線,其中第二組的點最低、第三組回升。右邊的面板標題為「Non-linearity detected」,橫軸是黃體素受體 0 到 679 fmol/l:藍色樣條曲線先微幅上升,在約 23 fmol/l 處達到 1.053 的高點,越過 63 fmol/l 之後才轉為下降,到約 491 fmol/l 落到最低的 0.793,右端略回升到 0.806;紅色虛線幾乎貼在 1 附近緩慢下降,明顯沒有跟上曲線的下降段;綠色階梯最右邊那一階(最高四分位)落在 0.81 附近,低於同一位置的紅線而貼近藍色曲線。
同一組軸上的三種模型。左邊的曲線繞著直線走、未偵測到偏離,切組只是把同一條關係變粗糙;右邊的直線根本沒有貼到資料,而切組與樣條都抓到了那個下降段。產圖腳本 figures/scripts/B2-11-categorisation.R

P for trend 到底在算什麼

P for trend 在臨床論文裡幾乎是四分位表格的標配,但它的算法比多數人以為的粗糙: 把四分位編號 1、2、3、4 當成一個數值變項丟進模型,然後看那一個係數的 p 值。

於是它假設了兩件事:

  1. 單調:效果隨組別往同一個方向走。
  2. 等距:從 Q1 到 Q2 的 log-odds(或 log-hazard)變化量, 等於從 Q3 到 Q4 的變化量。

第二條是關鍵,而且幾乎沒有人檢查。四分位在原始尺度上不是等距的—— 方向 B 的四組中位數是 0、16、99、413 fmol/l, 最後一組是前一組的 4.2 倍。把它們當成 1、2、3、4 等距,等於宣稱「效果隨排名等速變化」, 那是一個關於組的序號的假設,不是關於原始變項的假設。

「最佳切點」:一個一定會偏大的效果量

比切四分位更常見、也更糟的做法:掃過所有可能的切點,挑 p 值最小的那個當「最佳切點」

拿方向 A 的 lwt 實際跑一遍。在第 10 到第 90 百分位之間, 共有 48 個相異值可以當切點,每一個都跑一次校正後的 logistic:

切點ORp
搜出來的「最佳」切點105 磅3.0530.005(未校正)
同一個對比,連續模型說的1.7120.036

第二列是這樣算的:切點兩側的平均體重分別是 97.19 與 137.76 磅, 把這個差距代進連續模型,得到的 OR 是 1.712。 搜出來的那個 3.053 是它的 1.78 倍。

有些變項根本切不出四分位

切組還有一個實務上會擋住你的地方:分位數切點必須互不相同。 同一份 rotterdam 資料裡的 nodes(陽性淋巴結數)就切不出來:

百分位0%25%50%75%100%
nodes 的切點001434

前兩個切點都是 0,因為 1436 位病人 (48.2%)沒有陽性淋巴結。 cut() 直接停下來報錯:'breaks' are not unique (英文語系下的訊息;中文語系的 R 會看到翻譯過的版本)。

這不是 R 的毛病,是四分位這個概念對零膨脹的變項沒有意義—— 沒有辦法把一半都落在同一個值上的資料切成四等份。 同一個零膨脹在樣條那一頁造成的是另一種災情(預設 knot 被擠在一起), 處理方式是手動指定 knot;而切組在這裡連跑都跑不起來。

臨床上常見的零膨脹變項:淋巴結數、住院天數、每日抽菸支數、急診就診次數、過去一年住院次數。

那什麼時候可以切?

常見誤用

誤用為什麼錯
把連續變項切成二分再做主要分析損失最多的一種切法;等於丟掉組內所有變異
用資料搜出「最佳切點」再照樣報 p 值效果量被選擇性放大,p 值沒有校正搜尋
切完比較顯著就採用切組版本那是線性假設不成立的訊號,該換樣條不是換切法
P for trend 顯著就說「有劑量反應關係」該檢定假設單調且等距,兩者都沒被檢查
四分位的 CI 跨過 1 卻描述效果大小應寫「未偵測到差異」並附區間
只報 Q4 vs Q1,不報各組人數與事件數讀者無法判斷估計是幾個人撐起來的
在不同論文之間比較四分位的 OR切點來自各自的資料分佈,定義的對比不同
零膨脹變項硬切分位數切點會重複,切出來的組也沒有臨床意義
切組之後宣稱「不需要假設線性」對,但代價是檢定力;樣條同樣不需要線性假設,卻不必付這個代價
主要分析用切組、次要分析才放連續順序反了;連續版本才是資訊完整的那個

所以,下一步

如果你讀到這裡的理由是「我的資料看起來不像直線」, 那要去的地方是限制性立方樣條與劑量反應曲線—— 那一頁用的是同一份 rotterdam 資料,示範怎麼在不切組的情況下放掉線性假設、 knot 要放在哪裡、以及畫出來的劑量反應曲線怎麼讀。

重跑本頁的所有數字

/opt/homebrew/bin/Rscript figures/scripts/B2-11-categorisation.R

讀讀看這張圖

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

同一個模型、同一個係數,母親體重的 odds ratio 被報成三個不同的數字。這說明什麼?

看答案與解析

正確答案: 每十磅是 0.876——OR 的大小取決於「每多少」,看到 OR 一定要先問單位

0.987、0.876、0.672 是同一個係數換三種單位的結果:每一磅、每十磅、每一個四分位距。三個都對,而且是同一件事——重點在於 OR 的大小沒有單位就沒有意義。每一磅那個版本看起來幾乎等於一,很容易被讀成「沒有效果」;每一個四分位距那個最遠離一,但它也不比另外兩個更「真」,只是換算的區間比較大。報告連續變項的 OR 時必須寫清楚每多少,否則讀者無法判斷效果大小。

用 quantile() 對 nodes 切四分位會直接以「breaks 不唯一」報錯。原因是什麼?

看答案與解析

正確答案: 有 1436 人的 nodes 是零,最低的幾個分位點因此相同

1436 人的 nodes 是零,將近全體的一半,於是最低的幾個分位點彼此相同,cut() 找不到唯一的切點就直接拒絕執行。1713 是事件數、2982 是總人數,兩者都不會讓分位點重疊——樣本大反而讓分位數更穩定。分位數切點在有大量重複值的變項上會失敗,而這種變項在臨床資料裡非常常見:零顆淋巴結、零次住院、零支菸。遇到這種分布,該想的是零要不要自成一組,而不是換一個切法硬切。

讀一張 spline 曲線圖時,第一個該找的是什麼?

看答案與解析

正確答案: 曲線通過一的位置 102——所有的比值都是相對於它

這張圖的參考點是 102,也就是曲線通過一的地方,而圖上每一個縱軸數值都是「相對於體重 102 磅的人」。121 是 lwt 的中位數、130 是平均數:參考點可以選成它們,但不是非得如此,這張圖就沒有。參考點的選擇不改變曲線的形狀,只把整條曲線上下平移,卻決定了所有數字是相對於誰——所以讀 spline 圖的第一個動作,是找出曲線通過一的那個位置在哪裡。

素材來源與授權

本頁為原創內容

回報內容問題

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

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

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

一併送出的資訊

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