ROC 曲線と ROC 曲線下面積     Last modified: Mar 27, 2008

目的

生データまたは度数分布表データに基づいて,ROC 曲線を描く。また,ROC 曲線下面積を計算する。

使用法・引数

疾病群,健康群の生データについて
ROC0(disease, normal, lowest=NULL, width=NULL)
  disease  疾病群の測定値ベクトル
  normal   健康者群の測定値ベクトル
  lowest   最も小さい値のキリのよい数値
  width    階級幅(計算精度)のキリのよい数値
           lowest か width がデフォルト値なら,データから適当に決める

度数分布表の形でまとめられているデータについて
ROC(x, disease, normal)
  x        分割表の下限値のベクトル(例題参照)
  disease  疾病群の度数分布ベクトル
  normal   健康者群の度数分布ベクトル

ソース

インストールは,以下の 1 行をコピーし,R コンソールにペーストする
source("http://aoki2.si.gunma-u.ac.jp/R/src/ROC.R", encoding="euc-jp")

# 生データまたは度数分布表データに基づいて,ROC 曲線を描く。また,ROC 曲線下面積を計算する
# 生データがあるとき(後述する ROC 関数も必要なので注意)
ROC0 <- function(    disease,                                # 疾病群の測定値ベクトル
                        normal,                                 # 健康者群の測定値ベクトル
                        lowest=NULL,                            # データの最小値より小さいキリのよい数値
                        width=NULL)                             # 度数分布を作成する階級幅のキリのよい数値
{
        my.hist <- function(x, brks)                         # R の hist 関数は,級限界の扱いがイヤラシイので自前の関数を書く
        {
                k <- length(brks)
                freq <- numeric(k)
                for (i in 1:(k-1)) {
                        freq[i] <- sum(brks[i] <= x & x < brks[i+1])
                }
                freq[k] <- sum(x >= brks[k])
                freq
        }

        x <- c(disease, normal)                                      # データをプールする
        min.x <- min(x)                                              # 最小値
        max.x <- max(x)                                              # 最小値
        cat("最小値 x = ", min.x, "\n")
        cat("最大値 x = ", max.x, "\n\n")
        if (is.null(lowest) || is.null(width)) {
                temp <- pretty(c(disease, normal), n=min(length(disease)+length(normal), 50))
                lowest <- temp[1]
                width <- diff(temp)[1]
                cat("最小値より小さいキリのよい数値 = ", lowest, "\n")
                cat("度数分布を作成する階級幅の切りのよい数値 = ", width, "\n\n")
        }
        
        brks <- seq(lowest, max.x+width, by=width)
        ROC(brks, my.hist(disease, brks), my.hist(normal, brks))
        
}
# 度数分布表しかないとき(生データから計算されるときにも,下請けとして使う)    
ROC <- function(     x,                                      # 分割表の下限値のベクトル
                        disease,                                # 疾病群の度数分布ベクトル
                        normal)                                 # 健康者群の度数分布ベクトル
{
        k <- length(x)                                               # 度数分布表の長さ
        stopifnot(k == length(disease) && k == length(normal))    # データのチェック
        Sensitivity <- c(rev(cumsum(rev(disease)))/sum(disease), 0)
        False.Positive.Rate <- c(rev(cumsum(rev(normal)))/sum(normal), 0)
        Specificity <- 1-False.Positive.Rate
        plot(False.Positive.Rate, Sensitivity, type="b")
        abline(h=c(0, 1), v=c(0, 1))
        c.index <- sum(sapply(1:k, function(i) (False.Positive.Rate[i]-False.Positive.Rate[i+1])*(Sensitivity[i+1]+Sensitivity[i])/2)) # area under ROC curve
        result <- cbind(x, disease, normal, Sensitivity[-k-1], Specificity[-k-1], False.Positive.Rate[-k-1])
        rownames(result) <- as.character(1:k)
        colnames(result) <- c("Value", "Disease", "Normal", "Sensitivity", "Specificity", "F.P. rate")
        list(result=result, c.index=c.index)
}


使用例

参考にしたページにある例。

FRA <- c(100, 220, 230, 240, 250, 260, 270, 280, 290, 300, 320, 340, 360, 400)
FRA.disease <- c(3, 2, 1, 4, 7, 4, 16, 5, 3, 9, 10, 5, 10, 21)
FRA.normal <- c(25, 7, 19, 17, 7, 8, 7, 6, 2, 2, 0, 0, 0, 0)

ROC(FRA, FRA.disease, FRA.normal)

生データがあるときの例。

disease.x <- as.integer(rnorm(200, mean=110, sd=10))	# 平均値=110,標準偏差=10 のテストデータ(200ケース)
normal.x <- as.integer(rnorm(300, mean=100, sd=10))	# 平均値=100,標準偏差=10 のテストデータ(300ケース)

ROC0(disease.x, normal.x)

出力結果例

> FRA <- c(100, 220, 230, 240, 250, 260, 270, 280, 290, 300, 320, 340, 360, 400)
> FRA.disease <- c(3, 2, 1, 4, 7, 4, 16, 5, 3, 9, 10, 5, 10, 21)
> FRA.normal <- c(25, 7, 19, 17, 7, 8, 7, 6, 2, 2, 0, 0, 0, 0)

> ROC(FRA, FRA.disease, FRA.normal)
$result
   Value Disease Normal Sensitivity Specificity F.P. rate	# Value は階級の下限値(区間に含まれる)
1    100       3     25        1.00        0.00      1.00	# つまり,最初の階級は,100 以上,220 未満と考える
2    220       2      7        0.97        0.25      0.75	# F.P. rate は偽陽性率
3    230       1     19        0.95        0.32      0.68
4    240       4     17        0.94        0.51      0.49
5    250       7      7        0.90        0.68      0.32
6    260       4      8        0.83        0.75      0.25
7    270      16      7        0.79        0.83      0.17
8    280       5      6        0.63        0.90      0.10
9    290       3      2        0.58        0.96      0.04
10   300       9      2        0.55        0.98      0.02
11   320      10      0        0.46        1.00      0.00
12   340       5      0        0.36        1.00      0.00
13   360      10      0        0.31        1.00      0.00
14   400      21      0        0.21        1.00      0.00

$c.index	# ROC 曲線下面積
[1] 0.88215

以下のような図が描かれる

fig

> disease.x <- as.integer(rnorm(200, mean=110, sd=10))
> normal.x <- as.integer(rnorm(300, mean=100, sd=10))

> ROC0(disease.x, normal.x)
最小値 x =  68 
最大値 x =  132 

最小値より小さいキリのよい数値 =  68 
度数分布を作成する階級幅の切りよい数値 =  1 

$result
   Value Disease Normal Sensitivity Specificity   F.P. rate
1     68       0      1       1.000 0.000000000 1.000000000
2     69       0      0       1.000 0.003333333 0.996666667
3     70       0      0       1.000 0.003333333 0.996666667
4     71       0      0       1.000 0.003333333 0.996666667
5     72       0      0       1.000 0.003333333 0.996666667
6     73       0      1       1.000 0.003333333 0.996666667
7     74       0      0       1.000 0.006666667 0.993333333
8     75       0      2       1.000 0.006666667 0.993333333
9     76       0      1       1.000 0.013333333 0.986666667
  途中省略
59   126       2      0       0.035 1.000000000 0.000000000
60   127       1      0       0.025 1.000000000 0.000000000
61   128       1      0       0.020 1.000000000 0.000000000
62   129       1      0       0.015 1.000000000 0.000000000
63   130       0      0       0.010 1.000000000 0.000000000
64   131       0      0       0.010 1.000000000 0.000000000
65   132       2      0       0.010 1.000000000 0.000000000
66   133       0      0       0.000 1.000000000 0.000000000

$c.index
[1] 0.7734917

・ 参考にしたページ


・ 直前のページへ戻る  ・ E-mail to Shigenobu AOKI

Made with Macintosh