專家已經雙重審閱,尚未人工抽查

邊際結構模型與時間相依 IPTW

病人會中途開始用藥、停藥、換藥,而決定他換不換的那個指標,本身又是前一次治療造成的。這種變項放進迴歸會同時造成過度校正與碰撞子偏誤,不放進去則干擾沒處理——兩個都錯。加權是第三條路:這一頁用一份真值已知的模擬,把三條路的估計並排放,並示範穩定化權重怎麼配、變異數為什麼不能直接讀、IPCW 怎麼跟 IPTW 相乘。

為什麼這個方法值得有自己的一頁

你在論文裡撞到這一頁的時機大概是三種:Methods 寫著 patients who switched treatment、 寫著 time-updated covariates、或者寫著 per-protocol analysis 而且不只是把不服藥的人刪掉。 自己手上那份資料撞到的時機只有一種:病人會中途開始用藥、停藥、換藥,而不是在第一天就被分好組、 從此不動。

這種資料有一個標準迴歸處理不了的形狀。決定病人第二次要不要治療的那個指標—— CD4 數值、血壓、腎功能、疾病活動度——本身就是第一次治療造成的。它同時是後續治療的干擾因子, 又是先前治療的後果。標準迴歸對這種變項只有兩個選項:放進去,或不放。 這一頁要說明的是為什麼兩個都錯,以及第三條路長什麼樣。

站上有三個地方把讀者送到這裡:時間相依共變項那頁講到 「時間相依的中介兼混淆不能用標準 Cox 處理」、IPTW 那頁講到 「暴露會隨時間改變時只有時間相依的加權走得通」、目標試驗模擬 那頁講到「per-protocol 要處理隨時間改變的暴露」。這一頁是那三條線的終點, 所以它自己不再把你轉介回去——底下有完整的權重形式、可以照跑的程式碼、 以及一份真值已知的模擬拿來對答案。

治療與干擾互相餵養:feedback 是什麼

把時間軸縮到最短——兩次門診——就足以把問題整個攤開:

  • visit 0:病人接受或不接受治療,記作 A0A_0。在這份模擬裡它是隨機分派的。
  • visit 1:先量到一個臨床指標 L1L_1,再根據它決定第二次治療 A1A_1
  • 結局 YY:例如一年內的某個事件。

L1L_1 站在一個尷尬的位置。它是 A0A_0後果(治療改變了指標), 又是 A1A_1干擾因子(指標決定了第二次要不要治療,而指標本身也預測結局)。 這就是 treatment-confounder feedback:治療改變共變項,共變項再回頭決定下一次治療。

跨兩個門診時點的有向無環圖。底下一排由左到右四個圓圈節點,依序是 A0、L1、A1、Y,相鄰兩個之間各有一支藍色實線箭頭:A0 指向 L1、L1 指向 A1、A1 指向 Y。另外兩支藍色曲線箭頭從 A0 底下繞過去,一支彎到 A1、一支彎得更遠直接到 Y,避免穿過中間的節點。上方置中偏左有第五個節點 U,它的圈是灰底紅框、旁邊標著 unmeasured,代表未測量;從 U 出發有兩支紅色虛線箭頭,一支往左下指向 L1、一支往右下指向 Y。圖底下三個小標籤分別把 A0 標成 visit 0、把中段的 L1 與 A1 標成 visit 1、把 Y 標成 outcome。圖頂兩行說明文字寫著 L1 既是 A0 的後果又是 A1 的干擾因子,以及條件化 L1 會擋掉一條真實路徑並同時打開 A0 到 L1 到 U 到 Y 這條假路徑,而加權兩件都不做。
兩個時點就足以產生 feedback:A0 造成 L1,L1 決定 A1。虛線紅圈的 U 是未測量的共同原因,它是這一頁的關鍵——沒有它,直接把 L1 放進迴歸不會出錯。產圖腳本 figures/scripts/B6-08-msm.R

圖上還有一個沒被觀察到的 UU,它同時造成 L1L_1YY。臨床上這種東西到處都是: 沒被記錄下來的疾病嚴重度、體能狀態、社經條件、家屬支持——它們影響指標,也影響結局, 而資料庫裡沒有欄位。

模擬用的生成過程把上面每一條箭頭都寫成一行式子:

變項怎麼生出來的意思
Urnorm(n)未測量的共同原因,分析時完全看不到
A0rbinom(n, 1, 0.5)隨機分派,所以 visit 0 沒有干擾
L1logit 為 -0.50 + 1.50·A0 + 1.20·U被前一次治療推動,也被 U 推動
A1logit 為 -0.50 + 1.20·L1 + 0.30·A0看著指標決定,這就是 confounding by indication
Ylogit 為 -1.50 + -0.70·A0 + -0.70·A1 + 1.00·U兩次治療各自有保護效果,U 有害

實際生出來的世代長這樣:20,000 個人,事件率 13.4%。 A0A_0 沒治療的人裡有 40.4% 的 L1L_1 是陽性,有治療的則是 68.5%——這是 A0L1A_0 \to L_1 那支箭頭在資料裡的樣子。 而 L1L_1 陰性的人有 40.3% 接受第二次治療,陽性的則是 70.6%——這是 L1A1L_1 \to A_1。兩件事同時成立,feedback 就成立了。

「放進去」與「不放」,兩個都錯

不放進去也沒有比較好:L1L_1A1A_1 真正的干擾因子(它同時預測 A1A_1YY, 後者經由 UU),不處理就是 confounding by indication 原封不動留在估計裡。

三條路跑出來的合計 log odds ratio(A0A_0A1A_1 兩期都治療對兩期都不治療)是這樣:

做法A0A_0A1A_1合計離真值多遠
把 L1 放進迴歸-0.835-0.592-1.427(-1.544, -1.309)0.180
完全不校正-0.622-0.353-0.975(-1.073, -0.872)0.272
MSM,穩定化權重-0.593-0.580-1.173(-1.275, -1.064)0.074
真值(g-computation)-0.624-0.624-1.247

方向是可以事先推出來的,而資料也照著走:把 L1L_1 放進迴歸偏過頭 (-1.427,比真值離虛無值更遠),完全不校正偏不足(-0.975,比真值更靠近零), 加權落在中間而且最靠近真值(-1.173,差 0.074)。 三條路各偏一個方向,這正是這份模擬要示範的東西。

三個上下排列的森林圖面板,共用同一條橫軸,橫軸是 log odds ratio。面板 A 是第一期效果 A0,面板 B 是第二期效果 A1,面板 C 是兩期都治療對兩期都不治療的合計。每個面板裡由上到下四列,左側標籤依序是把 L1 放進迴歸的天真做法、完全不校正、MSM 加穩定化權重、以及以 g-computation 算出來的真值。前三列各畫一個方塊點估計加一條 95% bootstrap 信賴區間的橫線,前兩列用紅色、MSM 用藍色;第四列的真值用綠色菱形,並且有一條綠色垂直虛線貫穿整個面板標出真值的位置。另有一條灰色點線畫在零的位置。每一列的右側以文字列出點估計與區間上下限。面板 C 裡,把 L1 放進迴歸那一列的點落在綠色虛線的左邊也就是更負的一側,完全不校正那一列落在右邊也就是更靠近零的一側,MSM 那一列落在兩者之間、離綠色虛線最近。圖頂註明這是 n = 20,000、seed 20260823、500 次 bootstrap 的模擬世代。
同一份資料,三種分析,三個方向。合計那一格(面板 C)是這張圖的重點:天真校正偏過頭、不校正偏不足、加權落在最靠近綠色虛線的位置。產圖腳本 figures/scripts/B6-08-msm.R

加權是第三條路:MSM 在估什麼

先把估計目標寫清楚。用潛在結果的記號,Ya0,a1Y^{a_0, a_1} 是「假如這個人在 visit 0 被指定 a0a_0、在 visit 1 被指定 a1a_1,他會不會發生事件」。四種靜態策略各對應一個全世代的風險:

visit 0visit 1全世代風險
不治療不治療22.2%
治療不治療13.4%
不治療治療13.4%
治療治療7.6%

邊際結構模型就是直接對這四個風險配一個模型,而不是對「觀察到的 Y 條件在共變項上」配模型:

logitPr(Ya0,a1=1)=β0+β1a0+β2a1\operatorname{logit} \Pr\left(Y^{a_0, a_1} = 1\right) = \beta_0 + \beta_1 a_0 + \beta_2 a_1

「邊際」的意思是左邊沒有條件在任何共變項上——它講的是整個世代的風險,不是某一種病人的風險。 「結構」的意思是左邊是潛在結果,不是觀察到的結果。β1+β2\beta_1 + \beta_2 就是上面表裡 「兩期都治療」對「兩期都不治療」的 log odds ratio,也就是這一頁一路在追的那個數字。

那要怎麼在只有觀察資料的情況下估這個模型?把每個人依他實際接受的治療機率的倒數加權, 造出一個假想世代(pseudo-population):在那個世代裡,每個時點的治療分派都跟當時的共變項無關, 就像有人在每次門診擲了一次硬幣。

穩定化權重長什麼樣

未穩定化的權重是每個時點治療機率倒數的連乘。它會爆炸:只要某個人在某個時點接受的是 「以他的狀況幾乎不會有人給」的治療,分母就趨近零,那一個人就可以主宰整個分析。

穩定化權重在分子放回一個只用過去治療、不用共變項的機率:

SWi=k=0KPr(Ak=aikAˉk1=aˉi,k1)Pr(Ak=aikAˉk1=aˉi,k1, Lˉk=lˉik)SW_i = \prod_{k=0}^{K} \frac{\Pr\left(A_k = a_{ik} \mid \bar{A}_{k-1} = \bar{a}_{i,k-1}\right)}{\Pr\left(A_k = a_{ik} \mid \bar{A}_{k-1} = \bar{a}_{i,k-1},\ \bar{L}_k = \bar{l}_{ik}\right)}

上面那條橫槓表示「到該時點為止的全部歷史」。分母負責把共變項造成的干擾拿掉, 分子負責把「純粹由過去治療決定的那一部分」放回去,於是權重會集中在 1 附近而不是散開。 分子裡不可以放共變項,放了就等於把要拿掉的東西又加回來。

這份模擬的兩個模型是:分子 A1 ~ A0,分母 A1 ~ A0 + L1

權重的樣子:平均 1.000、標準差 0.284、範圍 0.653 到 1.517,有效樣本數(ESS)18,505, 是名目 n 的 92.5%。穩定化是它這麼乖的原因。 同一組權重的未穩定化版本——分子換成 1、不是邊際治療機率——落在 2.76 到 7.43 之間,平均 4.00, 最大值是穩定化版本的 4.90 倍、標準差是 5.20 倍。其中 2.00 倍只是記帳問題 (A0A_0 在這裡是隨機分派,visit 0 的分子是個常數),但有效樣本數還是掉到 17,597,是名目 n 的 88.0%, 對比穩定化版本的 92.5%。

長條圖,橫軸是治療與共變項的型態,共八根長條,每根底下的標籤是 A0 斜線 L1 斜線 A1 三個二元值的組合,由左到右依權重由小到大排列。縱軸是人數。每根長條上方印著該型態的穩定化權重數值。權重小於 1 的四根在左半邊,它們的型態是第二次治療與指標一致的那四群,其中人數最多的是 A0 等於 1、L1 等於 1、A1 等於 1 這一群;權重大於 1 的四根在右半邊,型態是第二次治療與指標不一致的那四群,人數相對少。圖頂兩行說明文字寫出權重的平均、範圍與有效樣本數,並註明 visit 0 的權重恰好是 1 因為 A0 是隨機分派的。
三個變項都是二元的,所以權重只有 8 個相異值——這是八個型態的長條圖,不是直方圖。被上加權的是右半邊那四群:他們的第二次治療沒有跟著指標走。產圖腳本 figures/scripts/B6-08-msm.R
A0 / L1 / A1人數穩定化權重第二次治療跟著指標走嗎
1 / 0 / 01,7310.653跟著走(被下加權)
0 / 1 / 12,7070.743跟著走(被下加權)
0 / 0 / 03,7170.812跟著走(被下加權)
1 / 1 / 14,9640.879跟著走(被下加權)
0 / 0 / 12,2831.307沒跟著走(被上加權)
1 / 1 / 01,8361.324沒跟著走(被上加權)
1 / 0 / 11,4021.424沒跟著走(被上加權)
0 / 1 / 01,3601.517沒跟著走(被上加權)

這張表值得多看兩眼,因為它把「加權到底在做什麼」變成看得見的東西: 權重大於 1 的四群,全部都是 L1L_1A1A_1 不一致的人——指標陽性卻沒治療、 或指標陰性卻治療了,共 6,881 人。他們在真實世界裡是少數, 但在假想世代裡被放大到跟其他人一樣多,好讓「治療」與「指標」脫鉤。 權重小於 1 的四群則相反,是照著指標走的多數人,他們被縮小。

換句話說,加權是靠那些沒有照著臨床邏輯走的病人把干擾撬開的。 這也解釋了為什麼正性(positivity)是這個方法的命門:如果指標陽性的人沒有一個不治療, 那一格就是空的,權重會趨近無限大或者根本估不出來,而你在平均權重上看不見這件事—— 要看 ESS、看最大值、看每一個型態的人數,也就是上面這張表。

動手跑一次:長表、兩階段

實作分兩個階段,中間隔著一份權重。這是 MSM 跟一般迴歸最不一樣的地方: 你會配兩次模型,而第一次配的那個模型的係數,你一眼都不會看—— 它只是拿來算權重的中間產物。

# 產生寬表 d。U 是未測量的干擾——少了它,把 L1 條件化只會過度校正,
# naive 模型看起來就會是對的,整頁的論點會被自己的數字推翻。
set.seed(20260823)
n  <- 20000
U  <- rnorm(n)                                   # 未測量的干擾,非有不可
A0 <- rbinom(n, 1, 0.5)
L1 <- rbinom(n, 1, plogis(-0.5 + 1.5 * A0 + 1.2 * U))
A1 <- rbinom(n, 1, plogis(-0.5 + 1.2 * L1 + 0.3 * A0))
Y  <- rbinom(n, 1, plogis(-1.5 - 0.7 * A0 - 0.7 * A1 + 1.0 * U))
d  <- data.frame(A0, L1, A1, Y)

# ── 階段一:權重模型(長表,一人一個 visit 一列)──────────────────────
# d 是寬表:一人一列,欄位 A0 / L1 / A1 / Y。先攤成長表,
# 因為權重是「每個時點各算一次再連乘」,長表讓迴圈只寫一次。
n <- nrow(d)
long <- rbind(
  data.frame(id = 1:n, visit = 0, A = d$A0, L = 0,     lagA = 0),
  data.frame(id = 1:n, visit = 1, A = d$A1, L = d$L1,  lagA = d$A0)
)

K  <- 1                    # 最後一個 visit 的編號
sw <- rep(1, n)            # 每個人一個累積權重,從 1 開始連乘

for (k in 0:K) {
  dk <- long[long$visit == k, ]
  dk <- dk[order(dk$id), ]

  # 分子:只放「過去的治療」。分母:再加上「當下的共變項」。
  # 分子絕對不能放共變項——放了就等於把要拿掉的干擾又加回來。
  num <- glm(A ~ lagA,     data = dk, family = binomial())
  den <- glm(A ~ lagA + L, data = dk, family = binomial())

  pn <- predict(num, type = "response")   # P(A = 1 | 過去治療)
  pd <- predict(den, type = "response")   # P(A = 1 | 過去治療 + 共變項)

  # 每個人拿的是「他實際接受的那個治療」的機率,不是 P(A = 1)
  sw <- sw * ifelse(dk$A == 1, pn, 1 - pn) / ifelse(dk$A == 1, pd, 1 - pd)
}

# ⚠️ 在這份模擬裡 visit 0 的 lagA 與 L 都是常數,兩個模型都退化成截距模型,
# 那一期的權重因此恰好是 1(R 會把常數項的係數報成 NA,那是預期的)。
# 真實資料的 visit 0 有基線共變項 L0,分母是 A ~ L0,權重不會是 1。

summary(sw)                       # 平均要接近 1;離 1 很遠就是模型設錯了
sum(sw)^2 / sum(sw^2)             # 有效樣本數 ESS

# ── 階段二:加權的結果模型,就是 MSM ─────────────────────────────────
# 左邊是結局,右邊只有治療——沒有 L1。共變項只出現在階段一的分母裡。
# ⚠️ suppressWarnings 是刻意的,不是在蓋掉配壞的模型:加權後
# w_i * y_i 不再是整數,glm 因此丟 non-integer #successes in a binomial glm!
# 點估計是正確的加權 score 解,只有 glm 內部的二項式帳本不高興。
msm <- suppressWarnings(
  glm(Y ~ A0 + A1, data = d, family = binomial(), weights = sw)
)
coef(msm)["A0"] + coef(msm)["A1"]   # 兩期都治療 vs 兩期都不治療

# ⚠️ 不要讀 summary(msm) 的標準誤。理由見下一節。

驗證環境:R 4.6.0 + jsonlite 2.0.0。全部用 base R,不需要任何額外套件;ipw 或 WeightIt 這類套件做的是同一件事的包裝版。

真值不是那個結構係數:非塌縮性

生成 YY 的那條式子裡,A0A_0A1A_1 的係數各是 -0.70, 合計 -1.40。但這一頁一路在對的真值是 -1.247,不是 -1.40。 兩個數字不一樣,而且不是誰算錯

差別在於它們是兩個不同的參數:

  • -0.70 是條件參數——「在 UU 固定的前提下,治療讓 log odds 變多少」。
  • -1.247 是邊際參數——「整個世代都治療 vs 整個世代都不治療,全世代風險的 log odds 差多少」。

odds ratio 是不可塌縮(non-collapsible)的:即使沒有任何干擾, 把一個有預測力的變項(這裡是 UU)從模型裡拿掉,係數也會往零縮。 這是 odds ratio 這個尺度本身的性質,不是偏誤——風險差與相對風險就沒有這個問題。

MSM 不是魔法,它也是一個模型

上面那張表裡,MSM 離真值還差 0.074。這個殘餘落差有一部分不是雜訊, 是模型設錯——而且錯在這一頁自己寫的那個工作模型上。

那個模型假設 A0A_0 的效果與 A1A_1 的取值無關(右邊只有 a0a_0a1a_1 兩個主效果,沒有交互作用項)。 但真值算出來的兩個對比其實不相等:A1A_1 固定在不治療時,A0A_0 的對比是 -0.612;A1A_1 固定在治療時是 -0.635, 差了 0.022。工作模型把這兩個不同的量當成同一個參數在估, 所以它報出來的東西是兩者的一種折衷。

這件事值得寫出來,因為 MSM 最常被誤解的地方就是這裡:加權處理的是干擾, 它不會替你把結果模型設對。 你仍然要決定要不要放交互作用項、要不要放時間的函數、 劑量要不要當連續變項。權重模型設錯會讓權重失真,結果模型設錯會讓估計目標本身跑掉, 兩個是各自獨立的失敗管道。

變異數為什麼不能直接讀

兩條可用的路:

  • Bootstrap(本頁採用)。 重抽個體,而且每一次重抽都要重配權重模型—— 只重跑結果模型、把權重當成算好的常數帶過去,就等於把上面第 2 點的錯誤原封不動搬進 bootstrap 裡。 本頁跑 500 次,表上所有的區間都來自它。
  • 穩健(sandwich)標準誤。 便宜、多數軟體按一個選項就有,但它把權重當成已知, 對穩定化權重通常偏保守。本頁也一併算了:MSM 的 A0A_0 是 0.045, bootstrap 是 0.045;A1A_1 是 0.044 對 0.046。兩者在這份資料上很接近,但這是資料給的,不是通則。

IPCW:另一個加權,而且可以跟 IPTW 相乘

上面處理的是「誰接受了治療」。真實的追蹤資料還有第二個選擇性的問題:誰還留在追蹤裡。 病人失聯、退出、換醫院,而退出的人往往跟留下來的人不一樣——如果退出的機率跟共變項和治療有關, 那麼「還在追蹤裡」本身就是一個被條件化的變項,偏誤的結構跟干擾一模一樣。

處理方式也一模一樣:設限加權(inverse probability of censoring weighting, IPCW)。 形式跟 IPTW 完全平行,只是把「接受治療的機率」換成「在該時點仍未被設限的機率」:

SWiC=k=0KPr(Ck=0Aˉk1,Cˉk1=0)Pr(Ck=0Aˉk1,Lˉk,Cˉk1=0)SW_i^{C} = \prod_{k=0}^{K} \frac{\Pr\left(C_k = 0 \mid \bar{A}_{k-1}, \bar{C}_{k-1} = 0\right)}{\Pr\left(C_k = 0 \mid \bar{A}_{k-1}, \bar{L}_k, \bar{C}_{k-1} = 0\right)}

實作上就是多配一個 logistic 模型(結果是「這一期有沒有被設限」), 把每個還在追蹤裡的人依他留下來的機率的倒數加權——留在追蹤裡的人要替那些跟他相似、 但已經退出的人發言

本頁的模擬沒有設限,所以只示範了 IPTW 那一半。真實資料上少做這一半, 等於默默假設了「退出是完全隨機的」——那是設限與截切那一頁 講的非資訊性設限假設,而在會換藥、會停藥的族群裡,它通常是最站不住的一條。

怎麼讀報表

論文裡的 MSM 通常只留下三、四句話加一張表。要檢查的是五件事:

  1. 權重模型的變項清單有沒有列出來,分子與分母分開列。 只寫「用 IPTW 校正」等於沒寫。 分子裡混進共變項是常見的實作錯誤,而它不會在任何診斷圖上現形。
  2. 每個時點都算了權重嗎,還是只算了基線? 只有基線權重的分析不是 MSM, 它是基線 IPTW,處理不了 feedback。
  3. 權重的分布有沒有報。 至少要有平均值(穩定化權重應該接近 1)、最大值、 以及有效樣本數。只報平均值看不出極端權重;本頁的 ESS 是名目 n 的 92.5%, 實務上掉到五成以下就要回頭檢查重疊。
  4. 有沒有截尾(truncation),截在哪裡,有沒有做敏感度分析。 截尾是用一點偏誤換變異數, 是可接受的決定,但必須事先講明並附上不截尾的結果。
  5. 標準誤是怎麼來的。 要看到 bootstrap 或 robust/sandwich 字樣。 什麼都沒寫的加權迴歸,八成報的是那個不能用的標準誤。

還有一件常被跳過的:結果模型的右邊應該只有治療(與必要的基線變項),不應該有時間相依共變項。 看到 MSM 的結果模型裡放著 LkL_k,那不是 MSM,那是這一頁第三節在警告的那個分析。

常見誤用

誤用為什麼錯
把時間相依共變項同時放進權重模型與結果模型等於做完加權又條件化一次,過度校正與碰撞子偏誤原封不動回來
分子裡放共變項那等於把要拿掉的干擾加回去,穩定化的意義消失
只算基線權重就叫 MSM基線加權處理不了「治療改變共變項、共變項再決定下一次治療」
只報平均權重平均值接近 1 跟有沒有極端值是兩件事,要看最大值與 ESS
直接讀加權迴歸的標準誤權重是估出來的、加權的列不是獨立觀察,區間會太窄
bootstrap 時不重配權重模型把權重的不確定性排除在外,等於白拿一份精確度
non-integer #successes 當成模型配壞那是加權的預期產物,點估計不受影響
沒有檢查正性(positivity)某個共變項型態下若沒有人接受(或都接受)治療,權重會爆炸或無法估
忘記 IPCW一旦因為偏離方案而設限,設限就是資訊性的,只加 IPTW 不夠
把 MSM 的係數當成「對一位病人的效果」它是邊際參數,講的是整個世代都治療對整個世代都不治療
拿 MSM 的 OR 去跟條件模型的 OR 比大小非塌縮性讓兩者本來就不相等,就算完全沒有干擾也不會相等

這一頁與其他頁的關係

  • 權重這個想法的起點——見 propensity score 加權(IPTW)。 那一頁講的是只有一個時點的版本;權重診斷那一套(平衡表、權重分布、ESS、截尾) 在這裡完全適用,只是要對每一個時點各做一次。
  • 箭頭要怎麼畫、要條件在哪些變項上——見 DAG 與干擾的結構。 本頁的碰撞子偏誤就是那一頁的 collider 規則在時間軸上的一個實例。
  • Cox 模型裡的時間相依共變項——見 時間相依共變項與長表。 那一頁教的是長表怎麼組、tmerge() 怎麼用,那份資料整理工作是本頁階段一的前置; 兩頁的分歧點在於共變項受不受暴露影響——不受影響就用那一頁的標準 Cox, 受影響就要走這一頁的加權。
  • per-protocol 分析的落點——見 目標試驗模擬。 那一頁定義了估計目標(ITT 還是 per-protocol)與時間零點,本頁提供 per-protocol 的估計手段。
  • 設限的假設——見設限與截切。IPCW 那一節換掉的是 非資訊性設限這個假設的處理方式,不是取消它。
  • 臨床落點——見資料庫研究那一章, 健保申報資料裡的用藥紀錄天生就是時間相依暴露。

重跑本頁的所有數字

/opt/homebrew/bin/Rscript figures/scripts/B6-08-msm.R

讀讀看這張圖

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

三條路的合計 log odds ratio:把時間相依共變項放進迴歸 -1.427、完全不校正 -0.975、MSM -1.173,而真值是 -1.247。把那個變項放進迴歸錯在哪?

看答案與解析

正確答案: 它擋掉經由那個變項的真實路徑,又在同一個變項上打開一條假路徑,最後偏離真值 0.180

那個時間相依共變項同時是三種東西:第一期治療的後代、第二期治療的干擾因子,以及它與未測量變項的共同後果。條件在它上面因此同時犯兩個方向相反的錯——擋掉一條真實的因果路徑(過度校正),又打開一條原本被它擋住的假路徑(碰撞子偏誤)。淨結果是偏了 0.180,落在比真值更遠離虛無值的一側,也就是 -1.427 對 -1.247。完全不校正的 -0.975 不是解方,它把第二期的干擾原封不動留著,偏得更多而且方向相反。加權的 -1.173 落在兩者之間,也最接近真值,這正是這份模擬要示範的東西。

面板 A 裡,完全不校正的第一期估計是 -0.622,比 MSM 的 -0.593 更接近真值 -0.624。可以據此說不校正比較好嗎?

看答案與解析

正確答案: 不行。第一期是隨機分派,那一格本來就沒有干擾要處理;同一個分析在第二期估出 -0.353

一個方法在某一格碰巧接近真值,不代表它做對了。第一期治療是隨機分派的,所以「完全不校正」在那一格本來就沒有干擾要處理,-0.622 貼近 -0.624 是設計送的;同一個分析到了第二期就估出 -0.353,而那一期的真值同樣在 -0.624 附近,差距一眼可見。至於 -0.593,那是 MSM 在第一期的估計,它略遠一點,但 MSM 針對的是合計對比那個量,單看一格的排名沒有意義。看單一係數挑贏家,跟看 p 值挑分析是同一種病。

這份模擬的第一期穩定化權重恰好是 1。真實資料能不能照抄這件事?

看答案與解析

正確答案: 不能。這裡第一次治療是隨機分派又沒有基線共變項,分子與分母是同一個模型,比值才恆為 1.00

第一期權重是 1.00,是這份模擬的設定送的:第一次治療隨機分派、而且沒有基線共變項,於是那一期的分子與分母是同一個模型。真實資料沒有這個好運——年齡、共病、疾病嚴重度同時決定第一次治療與結局,那一期需要自己的權重,形式跟第二期一模一樣。把這件事讀成「第一期不用算權重」,就是把整個基線干擾漏掉。1.52 是全體權重的最大值、0.93 是有效樣本數占名目的比例,兩個都在描述權重乖不乖,而權重乖不乖跟第一期要不要建模是兩件事。

同一組分母模型,把分子從邊際治療機率換成 1,權重的範圍從 0.65 到 1.52 變成 2.76 到 7.43。這個變化的重點是什麼?

看答案與解析

正確答案: 有效樣本數掉到名目樣本數的 0.88 倍:權重散開之後少數人的份量變重,估計的變異跟著變大

重點不是權重變大,是變散。平均升到 4.00 只是記帳:分子換成一個常數之後每個人的權重都乘上同一個倍數,樣本數並沒有變多,精確度也沒有變好。真正的代價寫在有效樣本數上——未穩定化只剩名目的 0.88 倍,因為權重的離散程度直接決定了少數人能不能主宰整個分析。4.90 是最大權重的倍率,它是離散的症狀而不是可以忽略的細節;平均值對得上完全不能保證離散度沒問題,這正是要看有效樣本數、看最大值、看每一個型態各有幾個人的理由。這裡的範圍從 0.65 到 1.52 變成 2.76 到 7.43,散開的幅度是看得見的。

生成結果的那條式子裡,兩期治療的係數各是 -0.7。但這一頁一路在對的真值是 -1.247。哪一個說法對?

看答案與解析

正確答案: -1.247 是邊際參數——整個世代都治療對整個世代都不治療,全世代風險的 log odds 差

這兩個數字回答的是不同的問題。其中 -0.700 是條件參數:在未測量變項固定的前提下,治療讓 log odds 變多少。而 -1.247 是邊際參數:整個世代都治療對整個世代都不治療,全世代風險的 log odds 差多少。odds ratio 不可塌縮,把一個有預測力的變項從模型裡拿掉,係數就會往零縮,即使完全沒有干擾也一樣——那是尺度的性質,不是偏誤。MSM 估的是邊際參數,所以它要對的是 -1.247;拿 -1.173 去跟結構係數比,會得到「MSM 也偏了」的錯誤結論,而那個落差有一部分只是尺度造成的。同一個道理在真實論文裡的形式是:校正過的與沒校正的 odds ratio 本來就不會相等。

MSM 的合計估計是 -1.173,真值是 -1.247,差了 0.074;同一次分析重抽出來的合計 bootstrap 標準誤是 0.057。關於這個殘差,哪一個說法站得住?

看答案與解析

正確答案: 殘差只有這個估計自己標準誤 0.057 的一倍多,所以它的大小不能拿來當作「還剩多少偏誤」的度量——這一頁指出的工作模型設錯是從模型假設看出來的,不是從這個差看出來的

先把殘差跟它自己的不確定度放在一起看。合計估計的 bootstrap 標準誤是 0.057,而殘差是 0.074,只有一個標準誤多一點;單一次模擬跑出這個大小的差,雜訊本身就足以解釋,所以這個數字不能拿來度量還剩多少偏誤。這一頁確實指出工作模型設錯了——右邊只有兩個主效果,而真值裡兩個第一期對比 -0.635 與 -0.612 並不相等——但那是從模型假設推出來的,不是從 0.074 讀出來的;而且兩個對比之間的落差比殘差小了一個量級,撐不起「差多少殘差就是多少」。至於權重,標準差 0.284 描述的是權重散不散;加大 bootstrap 的重抽次數只會讓標準誤本身估得更穩,不會縮小估計的抽樣誤差,更不會把點估計拉近真值。

加權迴歸的 summary() 印出來的標準誤為什麼不能直接讀?

看答案與解析

正確答案: 因為它把加權後的每一列當成獨立的二項觀察,又把權重當成已知常數,兩個假設都不成立;表上的 0.0445 是重抽算出來的

加權 glm 的標準誤同時做了兩個不成立的假設:把加權後的列當成獨立的觀察(一個權重 1.5167 的人是一個人,不是一個半的人),以及把權重當成已知的常數(權重是從同一批人估出來的,它自己帶著抽樣誤差)。0.0445 是 bootstrap 的結果,重抽的是個體,而且每一次都把權重模型重配一次;只重跑結果模型、把權重當成算好的常數帶進去,等於把第二個錯誤原封不動搬進 bootstrap 裡。0.0455 是穩健標準誤,那是另一條可用的路,但它同樣把權重當成已知,兩者在這份資料上接近是資料給的,不是通則。至於把權重同除以一個常數,那不會改變任何東西,因為問題不在權重的大小而在它的來源。

素材來源與授權

本頁為原創內容

回報內容問題

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

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

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

一併送出的資訊

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