Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Clinics/BlandAltmanPlot.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ On the percentage scale the bias is −6.4% with limits of about −25% to +13%:
::: callout-tip
### 5. Bland-Altman with Slope Test (Constant Bias Assessment)

The reference workflow adds a **slope test**: regress the differences on the averages and test whether the slope differs from zero \[6\]. A non-significant slope supports the constant-bias assumption; a significant slope indicates proportional bias.
The reference workflow adds a **slope test**: regress the differences on the averages and test whether the slope differs from zero \[4\]. A non-significant slope supports the constant-bias assumption; a significant slope indicates proportional bias.

```{r}
#| label: fig-5.1SlopeTest
Expand Down Expand Up @@ -260,4 +260,4 @@ Method-comparison plots are required when laboratories introduce a new assay or

\[3\] Datta D. blandr: a Bland-Altman Method Comparison package for R. Zenodo. 2017. doi:10.5281/zenodo.824514

\[6\] Xiaofan Lu, et al. FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. 2025. doi:10.1002/imm3.70005
\[4\] Xiaofan Lu, et al. FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. 2025. doi:10.1002/imm3.70005
6 changes: 2 additions & 4 deletions Clinics/BlandAltmanPlot.zh.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ ggplot(method_data, aes(x = avg, y = pct_diff)) +
::: callout-tip
### 5. 带\u659c率检验的 Bland-Altman 图(恒定偏倚评估)

参考工作流增加了**斜率检验**:将差值对均值做回归,检验斜率是否偏离零 \[6\]。斜率不显著支持标准 Bland-Altman 方法的恒定偏倚假设;斜率显著则提示比例偏倚。
参考工作流增加了**斜率检验**:将差值对均值做回归,检验斜率是否偏离零 \[4\]。斜率不显著支持标准 Bland-Altman 方法的恒定偏倚假设;斜率显著则提示比例偏倚。

```{r}
#| label: fig-5.1SlopeTest
Expand Down Expand Up @@ -238,8 +238,6 @@ legend("topleft", bty = "n", cex = 0.8,
- 临界差异为 ±1.96 × 差值标准差;斜率 ≠ 0 意味着该值在全范围内非常数。
:::

## Practice tips

## 实践要点

- x 轴应使用两种方法的*均值*(真值的最佳估计),切勿只用其中一种方法——以单一方法为横轴会在差值中引入虚假相关。
Expand All @@ -262,4 +260,4 @@ legend("topleft", bty = "n", cex = 0.8,

\[3\] Datta D. blandr: a Bland-Altman Method Comparison package for R. Zenodo. 2017. doi:10.5281/zenodo.824514

\[6\] Xiaofan Lu, et al. FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. 2025. doi:10.1002/imm3.70005
\[4\] Xiaofan Lu, et al. FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. 2025. doi:10.1002/imm3.70005
69 changes: 69 additions & 0 deletions Clinics/DCAPlot.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,73 @@ ggplot(impact, aes(x = threshold)) +

The gap between the two lines is the number of unnecessary interventions per 1000 patients at each threshold — small gaps at clinically relevant thresholds indicate a useful model.

### 5. Many Models at One Horizon: Value and Over-Intervention

The FigureYa33 layout \[4\] puts **every candidate model on one decision curve** — including a deliberately weak single-variable model — so the reader sees both halves of the clinical argument: above "treat all" a model justifies *intervening* on high-risk patients (opt-in), and the interventions-avoided view quantifies whom you may safely *spare* (opt-out). The simulated cohort below carries four risk scores for the same 2-year mortality horizon: a full model, its clinical-only and biomarker-only components, and age alone.

```{r}
#| label: fig-5.1FourModelDCA
#| fig-cap: "Decision curves for four risk models at the 2-year horizon (simulated cohort, n = 500): net benefit against treat-all and treat-none defaults."
#| out.width: "85%"
#| warning: false
#| message: false
#| fig-width: 8
#| fig-height: 5.5

set.seed(3311)
n_dc <- 500
lc <- data.frame(
age = rnorm(n_dc, 60, 9),
stage = factor(sample(c("I", "II", "III"), n_dc, TRUE)),
ecog = sample(0:2, n_dc, TRUE, prob = c(0.5, 0.35, 0.15)))
lp <- -0.9 + 0.024 * (lc$age - 60) + c(0, 0.4, 0.8)[as.integer(lc$stage)] + 0.25 * lc$ecog
H <- exp(lp) * 0.4 # cumulative hazard at 730 days
S730 <- exp(-H)
event_time <- -log(runif(n_dc)) / H * 730
cens <- rexp(n_dc, 1 / 1500)
lc$time <- pmin(event_time, cens, 1095)
lc$event <- as.integer(event_time <= lc$time)
## name the columns what the legend should say (dcurves uses variable names)
lc$`Full model` <- 1 - S730
lc$`Clinical only` <- 1 - exp(-exp(-0.9 + 0.024 * (lc$age - 60) +
c(0, 0.4, 0.8)[as.integer(lc$stage)]) * 0.4)
lc$`Biomarker only` <- pmin(0.95, pmax(0.01, 0.2 + 0.14 * lc$ecog + rnorm(n_dc, 0, 0.12)))
lc$`Age only (weak)` <- pmin(0.9, pmax(0.01, (lc$age - 40) / 60))

dca4 <- dca(Surv(time, event) ~ `Full model` + `Clinical only` +
`Biomarker only` + `Age only (weak)`,
data = lc, time = 730, thresholds = seq(0, 0.5, 0.01))
plot(dca4, smooth = FALSE) +
labs(x = "Threshold probability (2-year mortality)", y = "Net benefit") +
theme_bw(base_size = 11) +
theme(legend.position = "top")
```

```{r}
#| label: fig-5.2FourModelNIA
#| fig-cap: "Net interventions avoided per 100 patients for the same four models: the value of a model is how many treat-all interventions it can spare at equal missed events."
#| out.width: "85%"
#| warning: false
#| message: false
#| fig-width: 8
#| fig-height: 5.5

nia4 <- net_intervention_avoided(dca4, nper = 100)
plot(nia4, smooth = FALSE) +
labs(x = "Threshold probability (2-year mortality)",
y = "Interventions avoided per 100 (vs treat all)") +
theme_bw(base_size = 11) +
theme(legend.position = "top")
```

::: callout-tip
**Practice tips**

- Always include a **weak reference model** (one variable, or a noisy biomarker): it anchors the reader's expectations, and a candidate model that cannot beat it has no place in the clinic.
- `dcurves::dca()` accepts `labels =` to rename models in the legend — display model names a clinical reader knows, not R variable names.
- The net-benefit and interventions-avoided views are two readings of the same curve: report both when the paper's question is *whom to spare* rather than *whom to treat*.
:::

## Application

Decision curves are routinely reported in clinical prediction-model studies next to ROC and calibration curves. The panel below shows the typical pairing: (A) decision curves across thresholds and (B) the clinical impact curve.
Expand All @@ -195,4 +262,6 @@ Decision curves are routinely reported in clinical prediction-model studies next

\[3\] Sjoberg DD. dcurves: Decision Curve Analysis for Model Evaluation. R package version 0.5.1. doi:10.32614/CRAN.package.dcurves

\[4\] Xiaofan Lu, et al. FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. 2025. doi:10.1002/imm3.70005

\[4\] Loprinzi CL, Laurie JA, Wieand HS, et al. Prospective evaluation of prognostic variables from patient-completed questionnaires. North Central Cancer Treatment Group. J Clin Oncol. 1994;12(3):601-607. doi:10.1200/JCO.1994.12.3.601
69 changes: 69 additions & 0 deletions Clinics/DCAPlot.zh.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,73 @@ ggplot(impact, aes(x = threshold)) +

两条线之间的差值就是每个阈值下每 1000 名患者中“不必要的干预”数量——在临床相关阈值处差值越小,说明模型越有用。

### 5. 一个 horizon 上的多模型比较:获益与避免过度干预

FigureYa33 版式 \[5\] 把**所有候选模型放进同一张决策曲线**——包括一个刻意弱化的单变量模型——让读者同时看到临床论证的两半:高于"全部干预"基线时,模型支持对高危者*干预*(opt-in);"避免干预数"视角则量化可以安全*放过*谁(opt-out)。下面的模拟队列对同一个 2 年死亡 horizon 构造四个风险评分:完整模型、其临床与生物标志物成分、以及单独年龄。

```{r}
#| label: fig-5.1FourModelDCA
#| fig-cap: "四个风险模型在 2 年 horizon 的决策曲线(模拟队列,n = 500):相对 treat-all 与 treat-none 默认策略的净获益。"
#| out.width: "85%"
#| warning: false
#| message: false
#| fig-width: 8
#| fig-height: 5.5

set.seed(3311)
n_dc <- 500
lc <- data.frame(
age = rnorm(n_dc, 60, 9),
stage = factor(sample(c("I", "II", "III"), n_dc, TRUE)),
ecog = sample(0:2, n_dc, TRUE, prob = c(0.5, 0.35, 0.15)))
lp <- -0.9 + 0.024 * (lc$age - 60) + c(0, 0.4, 0.8)[as.integer(lc$stage)] + 0.25 * lc$ecog
H <- exp(lp) * 0.4 # 730 天的累积风险
S730 <- exp(-H)
event_time <- -log(runif(n_dc)) / H * 730
cens <- rexp(n_dc, 1 / 1500)
lc$time <- pmin(event_time, cens, 1095)
lc$event <- as.integer(event_time <= lc$time)
## 列名即图例名(dcurves 直接用变量名)
lc$`Full model` <- 1 - S730
lc$`Clinical only` <- 1 - exp(-exp(-0.9 + 0.024 * (lc$age - 60) +
c(0, 0.4, 0.8)[as.integer(lc$stage)]) * 0.4)
lc$`Biomarker only` <- pmin(0.95, pmax(0.01, 0.2 + 0.14 * lc$ecog + rnorm(n_dc, 0, 0.12)))
lc$`Age only (weak)` <- pmin(0.9, pmax(0.01, (lc$age - 40) / 60))

dca4 <- dca(Surv(time, event) ~ `Full model` + `Clinical only` +
`Biomarker only` + `Age only (weak)`,
data = lc, time = 730, thresholds = seq(0, 0.5, 0.01))
plot(dca4, smooth = FALSE) +
labs(x = "Threshold probability (2-year mortality)", y = "Net benefit") +
theme_bw(base_size = 11) +
theme(legend.position = "top")
```

```{r}
#| label: fig-5.2FourModelNIA
#| fig-cap: "同一四个模型每 100 名患者避免的干预数:模型的价值在于同等漏检下能省下多少 treat-all 干预。"
#| out.width: "85%"
#| warning: false
#| message: false
#| fig-width: 8
#| fig-height: 5.5

nia4 <- net_intervention_avoided(dca4, nper = 100)
plot(nia4, smooth = FALSE) +
labs(x = "Threshold probability (2-year mortality)",
y = "Interventions avoided per 100 (vs treat all)") +
theme_bw(base_size = 11) +
theme(legend.position = "top")
```

::: callout-tip
**实践要点**

- 务必放一个**弱参照模型**(单变量或含噪声的标志物):它锚定读者的预期——候选模型若赢不了它,就没有进临床的资格。
- `dcurves::dca()` 的图例直接使用变量名——把列命名为临床读者认识的名字(本例用反引号列名实现),而不是 R 变量名。
- 净获益与避免干预数是同一条曲线的两种读法:论文问题如果是"放过谁"而非"治疗谁",两个视角都要报告。
:::

## 应用

决策曲线通常与 ROC 曲线、校准曲线一同出现在临床预测模型研究中。下图展示典型的组合方式:(A) 各阈值下的决策曲线;(B) 临床影响曲线。
Expand All @@ -196,3 +263,5 @@ ggplot(impact, aes(x = threshold)) +
\[3\] Sjoberg DD. dcurves: Decision Curve Analysis for Model Evaluation. R package version 0.5.1. doi:10.32614/CRAN.package.dcurves

\[4\] Loprinzi CL, Laurie JA, Wieand HS, et al. Prospective evaluation of prognostic variables from patient-completed questionnaires. North Central Cancer Treatment Group. J Clin Oncol. 1994;12(3):601-607. doi:10.1200/JCO.1994.12.3.601

\[5\] Xiaofan Lu, et al. FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. 2025. doi:10.1002/imm3.70005
Loading
Loading