之前我寫過一篇使用pROC包畫好看的ROC曲線的教程,那篇教程中使用的是pROC,這個包可以快速擬合ROC曲線,然而這個包需要提前進行運算結果,并且不能直接顯示AUC值等,今天推薦一個另一個繪制ROC的包multipleROC,顧名思義,這個包是可以一次性繪制多條ROC曲線的,并且也是基于ggplot2。
目前這個包作者沒有上傳CRAN或BiocManager,只能通過Github安裝,地址為https://github.com/cardiomoon/multipleROC
安裝multipleROC
remotes::install_github("cardiomoon/multipleROC")
如果無法訪問GitHub,也可以導入到Gitee后進行安裝
remotes::install_git("https://gitee.com/swcyo/multipleROC/")
數(shù)據(jù)演示
我們使用仙桃學術上的一個診斷性ROC示例數(shù)據(jù)為例進行演示(下載請點擊xlxs鏈接)。
library(readxl)
ROC <- read_excel("~/Desktop/ROC曲線.xlsx")
探索性分析
我們可以事先看一下group1和group2兩組在a變量中的差別,使用webr包,先看看結果如何
library(webr)
library(ggplot2)
library(dplyr)
library(tidyr)
ROC %>%
group_by(outcome) %>%
numSummaryTable(a)
outcome | n | mean | sd | median | trimmed | mad | min | max | range |
---|---|---|---|---|---|---|---|---|---|
group1 | 40.00 | 1.51 | 0.55 | 1.45 | 1.51 | 0.63 | 0.59 | 2.44 | 1.86 |
group2 | 32.00 | 1.00 | 0.55 | 1.00 | 0.99 | 0.63 | 0.13 | 1.99 | 1.86 |
也可以使用箱示圖和密度圖進行展示,見Figure 1所示。
p1<- ggplot(data=ROC)+geom_density(aes(x=a,fill=outcome),alpha=0.5)
p2<-ggplot(data=ROC)+geom_boxplot(aes(x=outcome,y=a,fill=outcome),alpha=0.5)
cowplot::plot_grid(p1,p2)
同法可以顯示b和c變量的結果,我們暫時以boxplot展示
p3<-ggplot(data=ROC)+geom_boxplot(aes(x=outcome,y=b,fill=outcome),alpha=0.5)
p4<-ggplot(data=ROC)+geom_boxplot(aes(x=outcome,y=c,fill=outcome),alpha=0.5)
cowplot::plot_grid(p2,p3,p4,labels = "AUTO",nrow = 1)
-- 雖然探索性分析可以判斷兩組的差異,但是無法確定最佳截斷值,也無妨評估預測效能。
ROC曲線的繪制
繪制ROC曲線是確定最佳截斷值的有用方法之一。您可以使用以下R命令執(zhí)行ROC分析。下面的R命令使一個類為multipleROC的對象,并進行繪圖。
由于默認的函數(shù)中分組需為0和1,因此需要將group1和group2進行賦值,我們將group1定義為0,group2定義為1,我們繪制a變量在兩組中的ROC圖片,我們可以使用multipleROC()
語句一步計算,可以看到最佳截斷值,AUC值,另外敏感度、特異度都是可以直接顯示的,見Figure 3所示。。
ROC$group<-ifelse(ROC$outcome=='group1',0,1) # 將group1定義為0,否則為1
library(multipleROC)
a=multipleROC(group~a,data=ROC)
如果不想顯示那么多結果的話,也可以plot_ROC()
函數(shù)一個個設置是否顯示
plot_ROC(a,
show.points = TRUE,
show.eta = TRUE,
show.sens = TRUE,
show.AUC = TRUE,
facet = FALSE )
AUC和p值
在Figure 3的右下角,您可以看到曲線下面積(AUC)和Wilcoxon秩和檢驗的p值。p值來自以下計算結果。
wilcox.test(ROC$a,ROC$group)
##
## Wilcoxon rank sum test with continuity correction
##
## data: ROC$a and ROC$group
## W = 4416, p-value = 1.294e-13
## alternative hypothesis: true location shift is not equal to 0
AUC值則通過multipleROC包的simpleAUC()
函數(shù)進行運算,函數(shù)如下:
simpleAUC <- function(df){
df=df[order(df$x,decreasing=TRUE),]
TPR=df$sens
FPR=df$fpr
dFPR <- c(diff(FPR), 0)
dTPR <- c(diff(TPR), 0)
sum(TPR * dFPR) + sum(dTPR * dFPR)/2
}
那么,我們直接直接只有simpleAUC(aauc直接看到完整的AUC值
simpleAUC(a$df) ## 函數(shù)法
## [1] 0.7328125
a$auc # 直接提取法
## [1] 0.7328125
同樣的,我們直接提取截斷點(cutpoint)和最佳截斷值(Optimal Cutoff value)
a$cutpoint
## [1] 0.5136663
a$cutoff
## a ## 54 1.082828
將結果轉(zhuǎn)換為pROC對象
如果你更習慣pROC的結果,使用multipleROC2roc()
函數(shù),可以直接將結果轉(zhuǎn)換為 pROC的roc 對象
a2<-multipleROC2roc(a)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
class(a) ##a的類型為multipleROC
## [1] "multipleROC"
class(a2) ##a2已經(jīng)轉(zhuǎn)換為roc的類型了
## [1] "roc"
pROC::auc(a2) ## 我們用pROC看auc的結果
## Area under the curve: 0.7328
我們可以使用pROC的繪圖函數(shù)對a2進行繪圖了,我們比較以下兩種結果吧,見Figure 4所示。
library(pROC)
p5<-ggroc(a2, legacy.axes = TRUE)+
geom_segment(aes(x = 0, xend = 1, y = 0, yend = 1),
color="darkgrey",linetype=4)+
theme_bw()+ggtitle("pROC")
p6<-plot(a)+ggtitle("multipleROC")
cowplot::plot_grid(p5,p6)
多個ROC曲線的繪制
可以用多個函數(shù)進行多個ROC的曲線,可以使用plot_ROC(list())
一個個繪制曲線,見Figure 5所示。
a=multipleROC(group~a,data=ROC,plot=FALSE)
b=multipleROC(group~b,data=ROC,plot=FALSE)
c=multipleROC(group~c,data=ROC,plot=FALSE)
plot_ROC(list(a,b,c),
show.eta=FALSE,#不顯示截點
show.sens=FALSE #不顯示各種率
)
當然,如果你不想寫那么多代碼的話,也可以直接使用plot_ROC2()
函數(shù)直接繪制,是不是簡單的多。
plot_ROC2(yvar="group",xvars=c("a","b","c"),dataname="ROC")
分面顯示
將三張圖放在一起,可以看到數(shù)值重疊影響顏值,我們可以用ggplot2的facet進行分面繪制。
plot_ROC(list(a,b,c),facet=TRUE)
可以發(fā)現(xiàn)分面的標簽默認是1,2,3,我們可以使用Y叔團隊開發(fā)的ggfun這個包的facet_set()
函數(shù)進行快速的修改
library(ggfun) ## 必須要先安裝好
plot_ROC(list(a,b,c),facet=TRUE)+
facet_set(label=c(`1`="a", `2`="b", `3`="c"))
換一種分面顯示
使用ggplot2包的facet_grid
可以換一個分面顯示方式
plot_ROC(list(a,b,c))+facet_grid(no~.)+
facet_set(label=c(`1`="a", `2`="b", `3`="c"))
由于是基于ggplot2語句,所以我們可以使用ggtitle
添加標題,還可以更換主題等等。。。