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

限制性立方樣條與劑量反應曲線

線性假設要怎麼放掉:knot 放在哪裡、零膨脹的臨床變項為什麼會把預設 knot 撞在一起、參考點怎麼選、為什麼信賴區間帶在參考點會掐成一個點,以及「整體關聯的 p」與「非線性的 p」為什麼一定要分開報。

這一頁在補一個一直被推薦、卻沒有人示範過的東西

站上已經在三個地方叫你「改用限制性立方樣條」:線性迴歸 談非線性時、迴歸模型診斷看殘差圖時、 以及 Cox 比例風險模型檢查連續變項假設時。這一頁是那三個指標的落點。

先講清楚要放掉的是哪一條假設。把一個連續變項直接丟進迴歸式:

logh(t)=logh0(t)+βx+\log h(t) = \log h_0(t) + \beta \cdot x + \cdots

這裡的 βx\beta \cdot x 隱含一句很強的話:xx 每增加一單位,對結果的影響都一樣大—— 從 0 到 1 顆淋巴結,跟從 15 到 16 顆,對 log hazard 的貢獻被強制設成同一個數字。 臨床上幾乎沒有人相信這件事,但它是預設值,而且不會有任何警告。

限制性立方樣條(restricted cubic spline, RCS;在 R 裡最常用的實作是 splines::ns(), natural spline)的做法是:把 xx 的範圍用幾個節點(knot)切成幾段,每段配一條三次曲線, 在 knot 處要求接得平滑,並且限制兩端為直線(這就是「restricted」與「natural」的意思—— 不加這個限制,資料最稀疏的兩端會翹得最厲害)。

這一頁的例子

survival::rotterdam 是荷蘭 Rotterdam 腫瘤中心的乳癌世代, 2982 位病人、1713 個 recurrence-free survival 事件 (復發或死亡,取先發生者)。暴露變項是 nodes,腋下陽性淋巴結數。

選這個變項有三個理由,而且三個都是資料本身的性質,不是為了舉例湊出來的:

  1. 它與復發的關係真的是非線性的——前幾顆陡升、之後轉平,這正是直線畫不出來的形狀。
  2. 2982 個人裡有 1436 個的 nodes 是零(48.2%), 這個零膨脹會把教科書的 knot 放置規則撞壞,見下一節。
  3. 零本身是臨床上認得的參考點(node-negative disease),曲線有一個讀者一看就懂的錨。
library(survival)
library(splines)
data(cancer, package = "survival")

rot <- rotterdam
rot$rfs     <- pmax(rot$recur, rot$death)
rot$rfstime <- ifelse(rot$recur == 1, rot$rtime, rot$dtime)

# 線性版本:一個參數,強制等距效果
fit_lin <- coxph(Surv(rfstime, rfs) ~ nodes + age + size + meno, data = rot)

# 樣條版本:knot 自己指定(為什麼不用預設,見下一節)
basis   <- ns(rot$nodes, knots = c(1, 4, 9), Boundary.knots = c(0, 20))
fit_spl <- coxph(Surv(rfstime, rfs) ~ basis + age + size + meno, data = rot)

# 完全不放 nodes,用來檢定「整體關聯」
fit_non <- coxph(Surv(rfstime, rfs) ~ age + size + meno, data = rot)

anova(fit_non, fit_spl)   # 整體關聯:有沒有關係
anova(fit_lin, fit_spl)   # 非線性:關係是不是直線

驗證環境:R 4.6.0 + survival 3.8.6 + splines 4.6.0。ns() 隨 R 本體附帶,不必另外安裝。

knot 放在哪裡,以及零膨脹的變項會出什麼事

最常被引用的規則來自 Harrell:三個 knot 放在第 10、50、90 百分位,四個放 5/35/65/95, 五個放 5/27.5/50/72.5/95。這條規則有它的道理——knot 放在資料密的地方,每一段才有足夠的人撐著。

但它是對「分佈連續」的變項說的。 這份資料的 nodes 分佈長這樣:

百分位5%25%50%75%95%
nodes001412

前兩個百分位都是零,因為將近一半的人(1436 位,48.2%) 沒有陽性淋巴結。照百分位放 knot,等於把好幾個 knot 疊在同一個點上,而那個點又剛好是下邊界。 R 的反應是自己把 knot 挪開,並丟一句警告:

所以這一頁改成明確指定:ns(nodes, knots = c(1, 4, 9), Boundary.knots = c(0, 20))。 內部 knot 選 1、4、9 顆 (臨床上會拿來分期的位置,也都落在資料密的地方), 邊界訂在 0 與 20 顆—— 上邊界不取最大值,因為超過那裡的人太少,那一段畫出來的是外插不是估計。

參考點:曲線在講「跟誰比」

樣條的係數本身沒有辦法唸——basis1basis4 各自不對應任何臨床量。 能唸的是曲線:固定其他共變項,把 xx 從參考值移到某個值,風險變成幾倍。

所以每一張劑量反應曲線都得先選一個參考點。本頁選 nodes = 0 (node-negative),理由是臨床上認得。常見的其他選法是中位數或第 10 百分位; 選哪一個不影響曲線的形狀,只是把整條曲線上下平移,也不影響任何檢定的 p 值。

劑量反應曲線。橫軸是腋下陽性淋巴結數 0 到 20 顆,縱軸是相對於 0 顆的 hazard ratio,取對數刻度。曲線從左下的 1 起步,前幾顆陡升——1 顆時 1.23、4 顆時 2.09、9 顆時 3.39——之後明顯轉平,在約 15 顆處達到最高的 3.84 左右,到 20 顆時略降為 3.55。淡藍色的 95% 信賴區間帶包在曲線兩側,在右端因為人數變少而變寬,在左端的參考點收斂成一個點。水平虛線畫在 hazard ratio = 1,垂直點線與一個空心圓標出參考點(0 顆)。圖的底部有一條灰色的分佈條,每一根直立的細棒代表一個整數的淋巴結數,棒高是該人數。比例尺是按非零組裡人最多的那一組(1 顆,367 位)定的,所以 0 顆那一根被截頂,畫出來與 1 顆那一根一樣高,實際上是 1436 位、占 48.2%;圖內以文字標註了這兩件事。
劑量反應曲線。底部的灰色細棒是 nodes 的分佈(棒高=人數,0 那一根已截頂,實際是 1436 位),提醒讀者曲線右段是少數人撐起來的——那裡的信賴區間帶也明顯變寬。產圖腳本 figures/scripts/B2-05-splines.R

兩個 p 值,兩個問題,一定要分開報

這是審稿最常抓的一點,也是 spec 裡點名的要求。樣條模型可以做兩個不同的概似比檢定:

檢定比較哪兩個模型問的問題χ²dfp
整體關聯(樣條)樣條 vs 完全不放 nodesnodes 跟結果有沒有關係?320.174< 0.001
整體關聯(線性)線性 nodes vs 完全不放同上,但只允許直線220.491< 0.001
非線性樣條 vs 線性那個關係是直線嗎?99.693< 0.001

兩個問題是獨立的,四種組合都可能發生:

  • 整體顯著、非線性不顯著:關係存在,而且本研究沒有偵測到偏離直線。線性模型夠用。
  • 整體顯著、非線性也顯著(本頁的情形):關係存在,而且直線描述不了它。
  • 整體不顯著、非線性顯著:少見但會發生——U 形關係的兩端往上、中間往下, 用一個線性係數去總結會互相抵消。只報線性模型的 p 會漏掉它。
  • 兩個都不顯著:本研究未偵測到關聯。注意這不等於「沒有關聯」, 只代表這份資料沒有提供足以偵測的證據。

線性模型到底錯在哪裡

把線性模型隱含的那條直線疊上去,就看得到代價。

同一張劑量反應圖上疊了兩條線。藍色實線是樣條曲線(含淡藍色 95% 信賴區間帶),從 1 陡升後在約 15 顆處轉平;紅色虛線是線性模型隱含的直線,在對數刻度上是一條穩定上升的斜線,起點同樣是 1,到 20 顆時升到 4.37。兩條線從很前面就分開,落差在中段最大(約 7.6 顆處,直線只有曲線的 0.57 倍);圖上以一小段垂直線標出 4 顆處的落差(樣條 2.09、直線 1.34)。之後直線持續上升並在接近 20 顆處穿過樣條曲線,末端高於樣條的點估計但仍落在信賴區間帶之內。
同一份資料、同一組共變項,差別只在 nodes 用一個參數還是 4 個。直線在絕大部分的範圍都落在曲線之下、只在尾端高過它,而尾端正是人最少的地方。產圖腳本 figures/scripts/B2-05-splines.R
陽性淋巴結數樣條的 HR(95% CI)線性模型說的 HR
01(參考)1.00
11.23(1.10–1.37)1.08
21.49(1.30–1.72)1.16
42.09(1.83–2.38)1.34
93.39(2.95–3.89)1.94
153.84(3.23–4.56)3.02
203.55(2.80–4.50)4.37

三件事值得停下來看:

  1. 低估最嚴重的是中段,不是最前面。 直線與曲線的比值在約 7.6 顆處掉到最低, 那裡線性模型給的 HR 只有樣條的 0.57 倍;1 顆處的比值是 0.88,落差小得多。 圖上標出的 4 顆(樣條 2.09、線性 1.34) 取的是臨床上病人最多的位置,不是落差最大的位置。 而從 1 顆到 15 顆這一整段,直線都落在樣條的信賴區間之外
  2. 尾端反過來被高估。 20 顆時線性模型外推到 4.37, 樣條給 3.55(2.80–4.50)。 這裡直線還在區間內,但那是因為那一段的人太少、區間已經寬到分不出兩者—— 區間寬不是兩個模型一致的證據。
  3. 斜率在前幾顆之後就明顯放緩。 從 0 到 4 顆,HR 從 1 升到 2.09; 從 4 到 9 顆再升到 3.39;而從 9 顆一路到 15 顆,只再升到 3.84,之後就不再上升。 臨床上這是說得通的:淋巴結轉移到某個程度之後,再多幾顆帶來的額外訊息有限。 線性模型結構上沒有能力表達這種轉平,它只能繼續往上。

這一頁與其他頁的關係

  • 想知道「那乾脆切成四分位不就好了」為什麼通常更糟—— 見連續變項要不要切組。 簡短版:切組是拿檢定力去換掉線性假設,而樣條可以只換掉假設、不付那個代價。
  • 殘差圖看出彎曲之後要怎麼辦——回到迴歸模型診斷
  • Cox 模型的連續變項假設——見 Cox 比例風險模型。 要注意這條假設(log hazard 對共變項為線性)與比例風險假設是兩件不同的事, 用樣條處理前者,不會修好後者。
  • 樣條也會出現在校準那一頁,但角色不同: 那裡是用樣條去畫「預測風險 vs 實際風險」的彈性校準曲線,暴露變項是模型自己的線性預測值。

常見誤用

誤用為什麼錯
直接用 ns(x, df = 3) 而沒有看警告零膨脹或高度離散的變項會讓 knot 被挪位,Methods 寫的位置與實際不符
只報一個 p 值「有沒有關聯」與「是不是直線」是兩個問題,審稿會問
非線性 p 不顯著就說「關係是線性的」只能說本研究未偵測到偏離線性
沒有寫參考點曲線的縱軸沒有定義,別人無法重現
信賴區間帶在參考點不是零寬標準誤算錯了,多半是用了 type = "terms" 的 SE
曲線畫到資料的最大值尾端是外插,形狀由少數幾個人決定
用高次多項式代替樣條多項式是全域的,一端的離群值會扳動另一端
看曲線形狀再回頭調 knot 直到「好看」那是用結果選模型,p 值與區間都失效
把樣條係數本身拿來解讀基底函數沒有臨床意義,能解讀的只有曲線
樣條處理好了就宣稱 Cox 模型假設都滿足比例風險是另一條假設,要另外檢查

重跑本頁的所有數字

/opt/homebrew/bin/Rscript figures/scripts/B2-05-splines.R

讀讀看這張圖

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

把 nodes 當成線性放進模型時,每多一個 node 的 HR 是 1.077。改用 spline 之後,nodes = 4 相對於 nodes = 0 的 HR 說明了什麼?

看答案與解析

正確答案: 2.09——比線性模型在同一位置給的高出不少,線性假設低估了這一段

spline 在 nodes = 4 給的是 2.09,而線性模型在同一個位置只給 1.34——線性假設把整段關係壓成一個固定倍率,於是在 node 少的那一端明顯低估。1.08 是「每多一個 node」的那個倍率,它是斜率不是某一點的對比,兩者不是同一個量。要緊的是將近一半的病人 node 數是零,曲線最陡的那一段正好落在人最多的地方。

檢定非線性用的是概似比檢定。它拿 spline 模型跟哪一個模型比,自由度因此是多少?

看答案與解析

正確答案: 跟把 nodes 當線性的模型比,自由度 3

非線性檢定問的是「線性夠不夠」,所以分母模型是線性模型,差的是 3 個參數。跟空模型比得到的自由度是 4,但那個檢定問的是「nodes 跟結果有沒有關係」——那個檢定幾乎一定會過,把它當成非線性的證據,等於用一個注定顯著的檢定去回答另一個問題。自由度 1 則是線性模型對空模型。分母模型選錯,是這一類檢定最常見的誤用。

如果改用 ns(nodes, df = 3) 讓 R 自動決定節點位置,會發生什麼?

看答案與解析

正確答案: 第一個內部節點落在 0.25——節點按分位數放,而近半數的人是零,於是節點擠在一起

自動放節點是按分位數放的,而這個變項有將近一半的人是零,分位數因此擠成一團,第一個內部節點落在 0.25,R 甚至印出了把內部節點推離邊界節點的警告。4.00 是 nodes 分布上四分之三的位置,不是第一個節點;1.00 是本頁手動指定的那一個。按分位數放節點在資料分散時是合理的預設,遇到大量的零就會失效——這種時候要自己指定節點,或先想清楚零是不是該分開處理。

素材來源與授權

本頁為原創內容

回報內容問題

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

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

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

一併送出的資訊

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