統(tǒng)計軟件
加載R包和數(shù)據(jù)
calibration 方法1
calibration 方法2
library(survival)
library(rms)
## Loading required package: Hmisc
## Loading required package: lattice
## Loading required package: Formula
## Loading required package: ggplot2
##
## Attaching package: 'Hmisc'
## The following objects are masked from 'package:base':
##
## format.pval, units
## Loading required package: SparseM
##
## Attaching package: 'SparseM'
## The following object is masked from 'package:base':
##
## backsolve
試試使用自帶數(shù)據(jù)lung數(shù)據(jù)集進行演示。
大多數(shù)情況下都是使用1代表死亡,0代表刪失,這個數(shù)據(jù)集用2代表死亡。但有的R包會報錯,需要注意!
rm(list = ls())
dim(lung)
## [1] 228 10
str(lung)
## 'data.frame': 228 obs. of 10 variables:
## $ inst : num 3 3 3 5 1 12 7 11 1 7 ...
## $ time : num 306 455 1010 210 883 ...
## $ status : num 2 2 1 2 2 1 2 2 2 2 ...
## $ age : num 74 68 56 57 60 74 68 71 53 61 ...
## $ sex : num 1 1 1 1 1 1 2 2 1 1 ...
## $ ph.ecog : num 1 0 0 1 0 1 2 2 1 2 ...
## $ ph.karno : num 90 90 90 90 100 50 70 60 70 70 ...
## $ pat.karno: num 100 90 90 60 90 80 60 80 80 70 ...
## $ meal.cal : num 1175 1225 NA 1150 NA ...
## $ wt.loss : num NA 15 15 11 0 0 10 1 16 34 ...
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:Hmisc':
##
## src, summarize
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
df1 <- lung %>%
mutate(status=ifelse(status == 1,1,0))
str(lung)
## 'data.frame': 228 obs. of 10 variables:
## $ inst : num 3 3 3 5 1 12 7 11 1 7 ...
## $ time : num 306 455 1010 210 883 ...
## $ status : num 2 2 1 2 2 1 2 2 2 2 ...
## $ age : num 74 68 56 57 60 74 68 71 53 61 ...
## $ sex : num 1 1 1 1 1 1 2 2 1 1 ...
## $ ph.ecog : num 1 0 0 1 0 1 2 2 1 2 ...
## $ ph.karno : num 90 90 90 90 100 50 70 60 70 70 ...
## $ pat.karno: num 100 90 90 60 90 80 60 80 80 70 ...
## $ meal.cal : num 1175 1225 NA 1150 NA ...
## $ wt.loss : num NA 15 15 11 0 0 10 1 16 34 ...
dd <- datadist(df1)
options(datadist = "dd")
構(gòu)建cox比例風(fēng)險模型:
# 1年
coxfit1 <- cph(Surv(time, status) ~ age + sex + ph.ecog + ph.karno + pat.karno,
data = df1, x=T,y=T,surv = T,
time.inc = 365 # 1 年
)
# m=50表示每次計算50個樣本,一般取4-6個點,u=365和上面的time.inc對應(yīng)
cal1 <- calibrate(coxfit1, cmethod="KM", method="boot",u=365,m=50,B=500)
## Using Cox survival estimates at 365 Days
然后就是畫圖:
plot(cal1,
#lwd = 2, # 誤差線粗細
lty = 0, # 誤差線類型,可選0-6
errbar.col = c("#2166AC"), # 誤差線顏色
xlim = c(0.4,1),ylim= c(0.4,1),
xlab = "Nomogram-prediced OS (%)",ylab = "Observed OS (%)",
cex.lab=1.2, cex.axis=1, cex.main=1.2, cex.sub=0.6) # 字體大小
lines(cal1[,c('mean.predicted',"KM")],
type = 'b', # 連線的類型,可以是"p","b","o"
lwd = 3, # 連線的粗細
pch = 16, # 點的形狀,可以是0-20
col = "tomato") # 連線的顏色
box(lwd = 2) # 邊框粗細
abline(0,1,lty = 3, # 對角線為虛線
lwd = 2, # 對角線的粗細
col = "grey70" # 對角線的顏色
) 再介紹一下多個校正曲線圖形畫在一起的方法。
# 2年
coxfit2 <- cph(Surv(time, status) ~ age + sex + ph.ecog + ph.karno + pat.karno,
data = df1, x=T,y=T,surv = T,
time.inc = 730 # 2 年
)
cal2 <- calibrate(coxfit2, cmethod="KM", method="boot",u=730,m=50,B=500)
## Using Cox survival estimates at 730 Days
畫圖:
plot(cal1,lwd = 2,lty = 0,errbar.col = c("#2166AC"),
xlim = c(0,1),ylim= c(0,1),
xlab = "Nomogram-prediced OS (%)",ylab = "Observed OS (%)",
col = c("#2166AC"),
cex.lab=1.2,cex.axis=1, cex.main=1.2, cex.sub=0.6)
lines(cal1[,c('mean.predicted',"KM")],
type = 'b', lwd = 3, col = c("#2166AC"), pch = 16)
plot(cal2,lwd = 2,lty = 0,errbar.col = c("#B2182B"),
xlim = c(0,1),ylim= c(0,1),col = c("#B2182B"),add = T)
lines(cal2[,c('mean.predicted',"KM")],
type = 'b', lwd = 3, col = c("#B2182B"), pch = 16)
abline(0,1, lwd = 2, lty = 3, col = c("#224444"))
legend("bottomright", #圖例的位置
legend = c("5-year","8-year"), #圖例文字
col =c("#2166AC","#B2182B"), #圖例線的顏色,與文字對應(yīng)
lwd = 2,#圖例中線的粗細
cex = 1.2,#圖例字體大小
bty = "n")#不顯示圖例邊框
不過這種方法是把多個模型放在一張圖上,不是同一個模型對應(yīng)多個時間點。
這種方法不能有缺失值。
# 刪除缺失值
df2 <- na.omit(df1)
library(survival)
# 構(gòu)建模型
cox_fit1 <- coxph(Surv(time, status) ~ age + sex + ph.ecog + ph.karno + pat.karno,
data = df2,x = T, y = T)
cox_fit2 <- coxph(Surv(time, status) ~ age + ph.ecog + ph.karno,
data = df2,x = T, y = T)
# 畫圖
library(riskRegression)
## riskRegression version 2022.03.22
set.seed(1)
cox_fit_s <- Score(list("fit1" = cox_fit1,
"fit2" = cox_fit2),
formula = Surv(time, status) ~ 1,
data = df2,
#metrics = c("auc","brier"),
#summary = c("risks","IPA","riskQuantile","ibs"),
plots = "calibration",
#null.model = T,
conf.int = T,
B = 500,
M = 50,
times=c(700) # limit the time range
)
plotCalibration(cox_fit_s,
xlab = "Predicted Risk",
ylab = "Observerd RISK")
## The default method for estimating calibration curves based on censored data has changed for riskRegression version 2019-9-8 or higher
## Set cens.method="jackknife" to get the estimate using pseudo-values.
## However, note that the option "jackknife" is sensititve to violations of the assumption that the censoring is independent of both the event times and the covariates.
## Set cens.method="local" to suppress this message.
當然也是可以用ggplot2畫圖的。
# 獲取數(shù)據(jù)
data_all <- plotCalibration(cox_fit_s,plot = F)
## The default method for estimating calibration curves based on censored data has changed for riskRegression version 2019-9-8 or higher
## Set cens.method="jackknife" to get the estimate using pseudo-values.
## However, note that the option "jackknife" is sensititve to violations of the assumption that the censoring is independent of both the event times and the covariates.
## Set cens.method="local" to suppress this message.
# 數(shù)據(jù)轉(zhuǎn)換
plot_df <- bind_rows(data_all$plotFrames) %>%
mutate(fits = rep(c("fit1","fit2"),c(56,48)))
# 畫圖
ggplot(plot_df, aes(Pred,Obs))+
geom_line(aes(group=fits,color=fits),size=1.2)+
scale_color_manual(values = c("#2166AC","tomato"),name=NULL)+
scale_x_continuous(limits = c(0,1),name = "Predicted Risk")+
scale_y_continuous(limits = c(0,1),name = "Observerd Risk")+
geom_abline(slope = 1,intercept = 0,lty=2)+
geom_rug(aes(color=fits))+
theme_bw()◆ 前瞻性聲明
本中心及與之相關(guān)的所分發(fā)的任何資料可能含有與相關(guān)企業(yè)未來業(yè)務(wù)、未來狀況和運營業(yè)績有關(guān)的前瞻性陳述、看法或意見,包括相關(guān)企業(yè)的預(yù)估、預(yù)測、目標和計劃。前瞻性陳述常常包含但不限于下列措辭,例如"目標"、"計劃"、"認為"、"希望"、"繼續(xù)"、"預(yù)計"、"旨在"、"打算"、"確保"、"將"、"可能"、"應(yīng)"、"會"、"或許"、"預(yù)期"、"估計"、"預(yù)測"或類似表述或其否定形式。
本中心的前瞻性陳述僅基于本報告截至發(fā)布日期的估計和假設(shè)。此類前瞻性聲明并非是本實中心對企業(yè)和相關(guān)藥品、耗材、醫(yī)療技術(shù)未來業(yè)績所做的任何預(yù)測或者定量結(jié)論,并涉及已知和未知的風(fēng)險、不確定性和其他因素。
◆ 醫(yī)學(xué)聲明
本中心所撰寫的報告、文件等包含的藥品信息可能并非在所有國家/地區(qū)適用,或在不同的國家/地區(qū)可能適用不同的商標、適應(yīng)癥或患者使用劑量。本中心旨在傳遞醫(yī)藥相關(guān)證據(jù)質(zhì)量信息,不構(gòu)成對任何藥物或診療方案的推薦或推廣。如您想了解更多疾病知識或藥品、診療相關(guān)信息,請咨詢醫(yī)療衛(wèi)生專業(yè)人士。
◆ 免責(zé)聲明
一、本網(wǎng)站提供報告中的部分信息是于報告標注日期前從第三方文獻、網(wǎng)站等資料中所收集的信息,本網(wǎng)站提供報告及信息僅供參考,不作為診斷、確診和治療依據(jù),不能成為任何享有法律效力的書面證明文件,不能代替專業(yè)醫(yī)學(xué)建議,訪問者不能憑借或依據(jù)本網(wǎng)站報告或信息進行疾病診治。若訪問者以此為診斷和治療依據(jù),由此可能引發(fā)的任何負面影響、損失由訪問者自行負責(zé),本網(wǎng)站不予負責(zé)。本網(wǎng)站已盡力確保網(wǎng)站所載內(nèi)容的準確性、完整性、及時性和應(yīng)用性,但不對此作任何的承諾和保證。除本聲明明示的條款外,其他一切因使用本網(wǎng)站而引致之任何意外、疏忽、誹謗、版權(quán)或知識產(chǎn)權(quán)侵犯及其所造成的損失,本網(wǎng)站不承擔(dān)任何法律責(zé)任。大融(深圳)數(shù)據(jù)咨詢服務(wù)有限公司由合法權(quán)利的第三方所有,受中國有關(guān)法律、法規(guī)及規(guī)章的保護。
三、您在使用本網(wǎng)站時,請遵守有關(guān)知識產(chǎn)權(quán)保護的規(guī)定。本網(wǎng)站內(nèi)容僅供您個人使用,除非經(jīng)大融(深圳)數(shù)據(jù)咨詢服務(wù)有限公司的事先書面許可,任何人不得為了商業(yè)目的使用本網(wǎng)站內(nèi)容或擅自對本網(wǎng)站內(nèi)容進行任何修改、復(fù)制、出版、分發(fā)、放映、廣播或再傳送等。
四、本聲明以及其修改權(quán)、更新權(quán)及最終解釋權(quán)均屬大融(深圳)數(shù)據(jù)咨詢服務(wù)有限公司所有。大融(深圳)數(shù)據(jù)咨詢服務(wù)有限公司有權(quán)對擁有版權(quán)的資料隨時進行修改和更新。
五、因本網(wǎng)站及本聲明產(chǎn)生的任何爭議,由本網(wǎng)站所有者所在地的法院管轄。
六、本聲明于2023年3月1日公布并生效,訪問者須仔細閱讀并同意本聲明。