zl程序教程

您现在的位置是:首页 >  其他

当前栏目

ROC阳性结果还是阴性结果?

2023-03-07 09:12:29 时间

关于ROC曲线的内容很重要,无论是在医学统计、机器学习,还是临床预测模型中,都是很重要的内容,大家务必要掌握!

大家都知道ROC曲线的横坐标是假阳性率,纵坐标是真阳性率,根据数据,我们可以计算很多个假阳性率和真阳性率,然后就可以在坐标轴上画出很多个点,把这些点连接成线就是ROC曲线了。

那这些横纵坐标的值到底是怎么计算的呢?

假如,我想根据ca125的值判定一个人到底有没有肿瘤,找了10个肿瘤患者,20个非肿瘤患者,都给他们测一下ca125,这样就得到了30个ca125的值。

set.seed(20220840)
ca125_1 <- c(rnorm(10,80,20),rnorm(20,50,10))

# 30个人的ca125的值如下
ca125_1
##  [1]  51.88470  82.45907 113.66834  63.49476  98.29077  63.27374  74.25079
##  [8]  80.22945  83.01740  99.17105  42.52889  54.56804  48.88383  65.67865
## [15]  44.73153  45.99028  55.82554  42.79242  60.84917  64.80764  51.11468
## [22]  43.40118  47.03850  44.75943  68.34163  60.83829  53.32599  59.92225
## [29]  46.46360  30.02914

假定前10个人是肿瘤,后20个人是非肿瘤。

outcome <- c(rep(c("肿瘤","非肿瘤"),c(10,20)))
outcome
##  [1] "肿瘤"   "肿瘤"   "肿瘤"   "肿瘤"   "肿瘤"   "肿瘤"   "肿瘤"   "肿瘤"  
##  [9] "肿瘤"   "肿瘤"   "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤"
## [17] "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤"
## [25] "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤" "非肿瘤"
df <- data.frame(`outcome`=outcome,
                 `ca125`=ca125_1
                 )
psych::headtail(df)
##     outcome  ca125
## 1      肿瘤  51.88
## 2      肿瘤  82.46
## 3      肿瘤 113.67
## 4      肿瘤  63.49
## ...    <NA>    ...
## 27   非肿瘤  53.33
## 28   非肿瘤  59.92
## 29   非肿瘤  46.46
## 30   非肿瘤  30.03

现在如果我们设置ca125>60,判断为肿瘤,ca125≤50判断为非肿瘤,就能得到如下的结果:

df1 <- transform(df, pred = ifelse(ca125>60,"猜他是肿瘤","猜他不是肿瘤"))
df1
##    outcome     ca125         pred
## 1     肿瘤  51.88470 猜他不是肿瘤
## 2     肿瘤  82.45907   猜他是肿瘤
## 3     肿瘤 113.66834   猜他是肿瘤
## 4     肿瘤  63.49476   猜他是肿瘤
## 5     肿瘤  98.29077   猜他是肿瘤
## 6     肿瘤  63.27374   猜他是肿瘤
## 7     肿瘤  74.25079   猜他是肿瘤
## 8     肿瘤  80.22945   猜他是肿瘤
## 9     肿瘤  83.01740   猜他是肿瘤
## 10    肿瘤  99.17105   猜他是肿瘤
## 11  非肿瘤  42.52889 猜他不是肿瘤
## 12  非肿瘤  54.56804 猜他不是肿瘤
## 13  非肿瘤  48.88383 猜他不是肿瘤
## 14  非肿瘤  65.67865   猜他是肿瘤
## 15  非肿瘤  44.73153 猜他不是肿瘤
## 16  非肿瘤  45.99028 猜他不是肿瘤
## 17  非肿瘤  55.82554 猜他不是肿瘤
## 18  非肿瘤  42.79242 猜他不是肿瘤
## 19  非肿瘤  60.84917   猜他是肿瘤
## 20  非肿瘤  64.80764   猜他是肿瘤
## 21  非肿瘤  51.11468 猜他不是肿瘤
## 22  非肿瘤  43.40118 猜他不是肿瘤
## 23  非肿瘤  47.03850 猜他不是肿瘤
## 24  非肿瘤  44.75943 猜他不是肿瘤
## 25  非肿瘤  68.34163   猜他是肿瘤
## 26  非肿瘤  60.83829   猜他是肿瘤
## 27  非肿瘤  53.32599 猜他不是肿瘤
## 28  非肿瘤  59.92225 猜他不是肿瘤
## 29  非肿瘤  46.46360 猜他不是肿瘤
## 30  非肿瘤  30.02914 猜他不是肿瘤

这样就能得出一个四格表:

xtabs(~outcome+pred,data = df1)
##         pred
## outcome  猜他不是肿瘤 猜他是肿瘤
##   非肿瘤           15          5
##   肿瘤              1          9

根据这个四格表我们就能算出目前的真阳性率和假阳性率:

真阳性率:猜他是肿瘤猜对的人数 / 所有肿瘤人数 假阳性率:猜他是肿瘤猜错的人数 / 所有非肿瘤人数

真阳性率 = 9 / (1+9) = 0.9 假阳性率 = 5 / (15+5) = 0.25

一个阈值就能算出1个真阳性率和假阳性率,多找几个阈值就能算出多个率,把这些率画在坐标轴里,再连成线,就是ROC曲线了。

此时,我们计算的是确定是肿瘤的真阳性率和假阳性率,画出来的也是确定是肿瘤的ROC曲线。

现在大家可以思考一个问题,如果我想知道的是确定不是肿瘤的能力,那算出来的东西还一样吗?

反过来可以吗?

一般情况下我们感兴趣的是确定是肿瘤的能力,此时真阳性率和假阳性率的计算如下:

# 首先是获得四格表
xtabs(~outcome+pred,data = df1)
##         pred
## outcome  猜他不是肿瘤 猜他是肿瘤
##   非肿瘤           15          5
##   肿瘤              1          9

真阳性率:猜他是肿瘤猜对的人数 / 所有肿瘤人数

假阳性率:猜他是肿瘤猜错的人数 / 所有非肿瘤人数

真阳性率 = 9 / (1+9) = 0.9

假阳性率 = 5 / (15+5) = 0.25

但是如果我们感兴趣的是确定为非肿瘤的能力呢?

# 此时四格表还是这个四格表
xtabs(~outcome+pred,data = df1)
##         pred
## outcome  猜他不是肿瘤 猜他是肿瘤
##   非肿瘤           15          5
##   肿瘤              1          9

但是真阳性率和假阳性率的计算已经变了!

假阳性率:猜他不是肿瘤猜错的人数 / 所有肿瘤人数 真阳性率:猜他不是肿瘤猜对的人数 / 所有非肿瘤人数

假阳性率 = 1 / (1+9) = 0.1 真阳性率 = 15 / (15+5) = 0.75

此时再多取几个阈值,画出来的就是阴性结果的ROC曲线。

不知道大家平时有没有关注过这个问题呢?

在R语言中很多画ROC曲线的包都会提供一个参数,让你可以自由选择ROC哪一个结果,一般默认都是阳性结果的ROC,比如这里的有肿瘤,如果你不放心,可以手动指定,想计算谁就计算谁!