美文网首页
01DCA曲线

01DCA曲线

作者: Jachin111 | 来源:发表于2023-02-11 21:55 被阅读0次

DCA (Decision Curve Analysis) 是一种评估临床预测模型、诊断试验和分子标记物的简单方法。传统的诊断试验指标如:敏感性,特异性和ROC曲线下面积仅测量预测模型的诊断准确性,未能考虑特定模型的临床效用,而 DCA的优势在于它将患者或决策者的偏好整合到分析中。这种理念的提出满足了临床决策的实际需要,在临床分析中的应用日益广泛。

DCA算法原理

我们先来理解简单的几个概念,只有理解了这些专有词汇,才能够把大数据分析与临床的实际应用结合起来,毕竟发文章只是一种展示科学的一种方式,更高的目标是实施到临床中,挽救更多人的性命,这是一种使命,也是一种责任吧。看定义,如下:
P:给真阳性患者施加干预的受益值(比如用某生化指标预测某患者有癌症,实际也有,予活检,达到了确诊的目的);
L:给假阳性患者施加干预的损失值(比如预测有癌症,给做了活检,原来只是个增生,白白受了一刀);
Pi:患者i有癌症的概率,当Pi > Pt时为阳性,给予干预。
所以较为合理的干预的时机是,当且仅当Pi × P >(1 -- Pi) × L,即预期的受益高于预期的损失。推导一下可得,Pi > L / ( P + L )即为合理的干预时机,于是把L / ( P + L )定义为Pi的阈值,即Pt。
但对二元的预测指标来说,如果结果是阳性,则强制Pi=1,阴性则Pi = 0。这样,二元和其他类型的指标就有了可比性。
然后我们还可用这些参数来定义真阳性(A)、假阳性(B)、假阴性(C)、真阴性(D),即:
A:Pi ≥ Pt,实际患病;
B:Pi ≥ Pt,实际不患病;
C:Pi < Pt,实际患病;
D:Pi < Pt,实际不患病。
我们有一个随机抽样的样本,A、B、C、D分别为这四类个体在样本中的比例,则A+B+C+D = 1。那么,患病率(π)就是A + C了。

rmda包

二分类模型DCA曲线

library(rmda)
data("dcaData")
set.seed(123)

# 构建一个基本的二分类模型
baseline.model <- decision_curve(Cancer ~ Age + Female + Smokes,
                                 data=dcaData,
                                 thresholds=seq(0, .4, by=.005),
                                 bootstraps=10)
# 单个模型绘制DCA决策曲线
plot_decision_curve(baseline.model,
                    curve.names="Baseline Model",
                    cost.benefit.axis=FALSE,
                    # col=c('red', "blue"),
                    confidence.intervals=FALSE,
                    standardize=FALSE)

构造一个全变量模型,及将其他剩余的变量都加入模型中,构建预测模型并做图

set.seed(123)
full.model <- decision_curve(Cancer ~ Age + Female + Smokes + Marker1 + Marker2,
                             data=dcaData,
                             thresholds=seq(0, .4, by = .005),
                             bootstraps=10)
plot_decision_curve(full.model,  
                    curve.names="Full Model",
                    cost.benefit.axis=FALSE,
                    #col= c('red','blue'),
                    confidence.intervals=FALSE,
                    standardize=FALSE)

将两个构建好的模型放在一张图上,以此来比较两个模型的性能

plot_decision_curve(list(baseline.model, full.model), 
                    curve.names=c("Baseline model", "Full model"),
                    col=c("blue", "red"),
                    lty=c(1, 2), 
                    lwd=c(3, 2, 2, 1),
                    legend.position="bottomright")
# 只需要显示两个模型的预测曲线即可
plot_decision_curve( list(baseline.model, full.model),
                     curve.names=c("Baseline model", "Full model"),
                     col=c("blue", "red"),
                     confidence.intervals=FALSE,  #remove confidence intervals
                     cost.benefit.axis=FALSE, #remove cost benefit axis
                     legend.position="topright") #add the legend

ggDCA包

必须通过git安装,否则后期会报错

# 训练集与验证集
library(caret)
library(ggDCA)


# if (!require(ggDCA)) {
#   devtools::install_github("yikeshu0611/ggDCA")
# }

train_id <- createDataPartition(y=LIRI$status, p=0.7, list=FALSE)
train_data <- LIRI[train_id,]
test_data <- LIRI[-train_id,]

logistic回归

library(rms)

ddist <- datadist(train_data)
options(datadist='ddist')

m1 <- lrm(status ~ ANLN, train_data)
m2 <- lrm(status ~ CENPA + GPR182 + BCO2, train_data)
m3 <- lrm(status ~ ANLN + CENPA + GPR182 + BCO2, train_data)
d_train <- dca(m1)
ggplot(d_train)

d_train <- dca(m1, m2, m3)
ggplot(d_train)
# 修改图例名称
d_train <- dca(m1, m2, m3, model.names=c("ANLN", "Other 3 genes", "All 4 genes"))
ggplot(d_train)



# 验证集
d_test <- dca(m3, new.data=test_data)
ggplot(d_test)

d_test <- dca(m1, m2, m3, new.data=test_data)
ggplot(d_test)

cox回归

# 训练集
ddist <- datadist(train_data)
options(datadist='ddist')


m1 <- cph(Surv(time, status) ~ ANLN, train_data)
m2 <- cph(Surv(time, status) ~ CENPA + GPR182 + BCO2, train_data)
m3 <- cph(Surv(time, status) ~ ANLN + CENPA + GPR182 + BCO2, train_data)

# 单个模型,不给times赋值,默认验证中位时间
d_train <- dca(m1)
ggplot(d_train)

# 单个模型多个时间点
times <- round(quantile(LIRI$time, c(0.25, 0.5, 0.75)), 2)
d_train <- dca(m1, times=times)
ggplot(d_train)


# 多个模型同一时间点
d_train <- dca(m1, m2, m3, times=2.14)
ggplot(d_train)

# 多个模型多个时间点
d_train <- dca(m1, m2, m3, times=c(1.4, 2.14, 2.98))
ggplot(d_train)

# 验证集
# 单个模型,单个时间
d_train <- dca(m1, times=2.14, new.data=test_data)
ggplot(d_train)

# 单个模型,多个时间点
times <- round(quantile(LIRI$time, c(0.25, 0.5, 0.75)), 2)
d_train <- dca(m1, times=times, new.data=test_data)
ggplot(d_train)

# 多个模型,同一时间点
d_train <- dca(m1, m2, m3, times=2.14, new.data=test_data)
ggplot(d_train)

# 多个模型多个时间点
d_train <- dca(m1, m2, m3, times=c(1.4, 2.14, 2.98))
ggplot(d_train)

dcurves包

1.对于二分类变量,包的函数可以基于预测概率及金标准构建DCA曲线及计算临床净获益。
2.mlr3包的prediction可以基于任意机器学习模型构建预测概率与金标准的data.table文件
3.本次分析首先整体走下dcurves包的流程,然后用一个二分类变量演示具体用法
4.mlr3prob包可以构建机器学习生存模型,模型可以预测患者的终点时间风险,类似于二分类变量也可以构建DCA曲线及临床获益。

逻辑回归模型

library(dcurves)
library(gtsummary)
library(tidyverse)

data("df_binary")

# 构建逻辑回归模型
mod <- glm(cancer ~ famhistory, df_binary, family=binomial)
# 构建表格
tbl <- tbl_regression(mod, exponentiate=TRUE)
tbl

# 构建DCA图
dca(cancer ~ famhistory, df_binary) %>% plot(smooth=TRUE)
# 调整x轴范围(预概率范围)
dca(cancer ~ famhistory, df_binary, thresholds=seq(0, 0.35, by=0.01)) %>% plot(smooth=TRUE)

多元逻辑回归模型

# 构建多元逻辑回归并获得预测概率
glm(cancer ~ marker + age + famhistory, df_binary, family=binomial) %>% 
  broom::augment(newdata=df_binary, type.predict="response") -> res
# 对比多元逻辑回归预测概率与家族史DCA曲线
dca(cancer ~ famhistory + cancerpredmarker, data=df_binary,
    thresholds=seq(0, 0.35, by=0.01)) %>%
  plot(smooth=TRUE)

利用发表文献构建已经模型的预测概率

df_binary_updated <- 
  df_binary %>%
  mutate(logodds_Brown=0.75*(famhistory)+0.26*(age)-17.5,
         phat_Brown=exp(logodds_Brown)/(1+exp(logodds_Brown)))
# 绘制DCA曲线进行对比
dca(cancer ~ phat_Brown,
    data=df_binary_updated,
    thresholds=seq(0, 0.35, by=0.01),
    label=list(phat_Brown="Brown Model")) %>%
  plot(smooth=TRUE)

联合诊断实验的DCA对比分析

# 构建联合实验数据集
df_binary_updated <- 
  df_binary_updated %>%
  mutate(high_risk=ifelse(risk_group=="high", 1, 0),  #单纯高风险
         joint=ifelse(risk_group=="high"|cancerpredmarker>0.15, 1, 0),  #两组评价方法取并集
         conditional=ifelse(risk_group=="high"| (risk_group=="intermediate"&cancerpredmarker>0.15), 1, 0))  #两种方法取条件并集

# 对比dca
dca(cancer ~ high_risk + joint + conditional, data=df_binary_updated, 
    thresholds=seq(0, 0.35, by=0.01)) %>%
  plot(smooth=TRUE)

增加诊断实验的并发症因素(理解为可以设定为并发症的发生概率)

harm_marker <- 0.0333  #并发症的概率为3%,作者认为是30次的倒数
# 计算中危组的并发症概率
intermediate_risk <- df_binary_updated$risk_group=="intermediate"
harm_conditional <- mean(intermediate_risk)*harm_marker

# 利用风险损害绘制DCA
dca_with_harms <- dca(cancer ~ high_risk + joint + conditional,
                      data=df_binary_updated,
                      harm=list(joint=harm_marker, conditional=harm_conditional),
                      thresholds=seq(0, 0.35, by=0.01))
plot(dca_with_harms, smooth=TRUE)

保存临床净获益(Net Benefit)

dca_with_harms %>% as_tibble() -> res;res
# 转换数据为长格式,观察不同模型的临床效益
dca_with_harms %>% as_tibble() %>%
  filter(threshold %in% seq(0.05, 0.35, by=0.05)) %>%
  dplyr::select(variable, threshold, net_benefit) %>%
  pivot_wider(id_cols=threshold, names_from=variable, values_from=net_benefit) -> res2;res2

绘制干预避风险图

dca(cancer ~ marker, data=df_binary, as_probability="marker") %>%
  net_intervention_avoided() %>%
  plot(smooth=TRUE)

生存分析的DCA曲线

library(survival)
data("df_surv")

cox_model <- coxph(Surv(ttcancer, cancer) ~ age + famhistory + marker, data=df_surv)
tbl_regression(cox_model, exponentiate=TRUE)
# 构建风险预测概率
df_surv$pred <- predict(cox_model, type="expected")
names(df_surv)
dca(Surv(ttcancer, cancer) ~ cancerpredmarker,
    data=df_surv,
    time=1,
    thresholds=seq(0, 0.50, by=0.01),
    label=list(cancerpredmarker="Prediction Model")) %>%
  plot(smooth=TRUE)

病例对照研究的DCA曲线

dca(casecontrol ~ cancerpredmarker,
    data=df_case_control,
    prevalence=0.15) %>%  #需要设定验前概率
  plot(smooth=TRUE)
data("df_case_control")

多元cox回归模型

library(dcurves)
library(gtsummary)
library(tidyverse)
library(survival)

data("df_surv")

# 构建cox回归方程
cox_model <- coxph(Surv(ttcancer, cancer) ~ age + famhistory + marker, data=df_surv)
tbl_regression(cox_model, exponentiate=TRUE)

# 构建风险预测概率
df_surv_updated <- broom::augment(cox_model,
                                  newdata=df_surv %>% mutate(ttcancer=1.5),
                                  type.predict="expected") %>%
  mutate(pr_failure18=1-exp(-.fitted)) %>%
  dplyr::select(-.fitted, -.se.fit)
# 构建指定时间发生事件数的数值向量是最为关键的内容,函数中应用了augment的方法,利用新数据对于患者在指定时间点(这里指定了ttcancer=1.5就是指定了时间)发生终点时间的数量。

# 将指定时间改变为2.5
df_surv_updated <- broom::augment(cox_model,
                                  newdata=df_surv %>% mutate(ttcancer=2.5),
                                  type.predict="expected") %>%
  mutate(pr_failure18=1-exp(-.fitted)) %>%
  dplyr::select(-.fitted, -.se.fit)

# 可以看到,这里的type指定了expected,就是指定时间的事件发生数,在预测新数据的时候我们通过指定时间点统一了时间这一变量。
# exp(-.fitted)这一变量就是指定时间点的生存概率,而用1减去这一变量就是终点事件发生的概率。


# 绘制生存分析的DCA曲线
dca(Surv(ttcancer, cancer) ~ pr_failure18 + cancerpredmarker,
    data=df_surv_updated,
    time=1.5,
    thresholds=1:50/100) %>%
  plot(smooth=TRUE)

相关文章

网友评论

      本文标题:01DCA曲线

      本文链接:https://www.haomeiwen.com/subject/aberkdtx.html