使用循环在 R 中创建多个混淆矩阵

Create multiple confusion matrices in R using loops

我正在尝试从一个数据帧创建多个混淆矩阵,每个矩阵都是根据数据帧中的不同条件生成的。

所以对于下面的数据框,我想要一个混淆矩阵,用于 Value = 1Value = 2Value =3

  observed predicted Value
       1      1      1
       0      1      1
       1      0      2
       0      0      2
       1      1      3
       0      0      3

并查看如下结果:

Value  Sensitivity  Specificity  PPV  NPV
1        .96            .71      .84  .95
2        .89            .63      .30  .45     
3        .88            .95      .28  .80

这是我用可重现的例子尝试过的。我正在尝试编写一个循环来查看每一行,确定是否 Age = 1,然后从预测列和观察列中提取值以生成混淆矩阵。然后我手动从混淆矩阵中提取值,写出 sen、spec、ppv 和 npv,并尝试将所有矩阵组合在一起。然后循环再次从 Age = 2.

开始
data(scat)
df<-scat %>% transmute(observed=ifelse(Site=="YOLA","case", "control"), predicted=ifelse(Location=="edge","case", "control"),Age)

x<-1 #evaluate at ages 1 through 5
for (i in dim(df)[1]) { #for every row in df
  while(x<6) { #loop stops at Age=5
    if(x=df$Age) {
      q<-confusionMatrix(data = df$predicted, reference = df$observed, positive = "case")
      sensitivity = q$table[1,1]/(q$table[1,1]+q$table[2,1])
      specificity = q$table[2,2]/(q$table[2,2]+q$table[1,2])
      ppv = q$table[1,1]/(q$table[1,1]+q$table[1,2])
      npv = q$table[2,2]/(q$table[2,2]+q$table[2,1])
      matrix(c(sensitivity, specificity, ppv, npv),ncol=4,byrow=TRUE)
    }
  }
  x <- x + 1 #confusion matrix at next Age value
}

final<- rbind(matrix) #combine all the matrices together

但是,这个循环完全不起作用。我不确定错误在哪里。

您的代码可以简化,并且可以像这样实现所需的输出:

library(caret)
library(dplyr)

data(scat)

df <- scat %>% 
  transmute(observed = factor(ifelse(Site == "YOLA","case", "control")), 
            predicted = factor(ifelse(Location == "edge","case", "control")),
            Age)

final <- t(sapply(sort(unique(df$Age)), function(i) { 
  
  q <- confusionMatrix(data      = df$predicted[df$Age == i],
                       reference = df$observed[df$Age == i], 
                       positive  = "case")$table
  
  c(sensitivity = q[1, 1] / (q[1, 1] + q[2, 1]),
    specificity = q[2, 2] / (q[2, 2] + q[1, 2]),
    ppv         = q[1, 1] / (q[1, 1] + q[1, 2]),
    npv         = q[2, 2] / (q[2, 2] + q[2, 1]))
}))

导致

final
#>      sensitivity specificity        ppv       npv
#> [1,]         0.0   0.5625000 0.00000000 0.8181818
#> [2,]         0.0   1.0000000        NaN 0.8000000
#> [3,]         0.2   0.5882353 0.06666667 0.8333333
#> [4,]         0.0   0.6923077 0.00000000 0.6923077
#> [5,]         0.5   0.6400000 0.25000000 0.8421053

但是,很高兴知道为什么您自己的代码不起作用,所以这里有一些问题可能对您有所帮助:

  1. 对于 confusionMatrix
  2. ,您需要因子列而不是字符列
  3. 您在 df 的行中递增,但您需要对每个唯一年龄进行一次迭代,而不是数据框中的每一行。
  4. 你增加 x 的行发生在 while 循环之外,所以 x 永远不会增加并且循环永远不会终止,所以控制台只是挂起。
  5. 您正在做 if(x = df$Age),但您需要 == 来测试相等性。
  6. 无论如何比较xdf$Age是没有意义的,因为x是长度1而df$Age是一个长向量。
  7. 你每次都做 q$table 会有不必要的重复。你可以让 q 等于 q$table 来让你的代码更易读并且更不容易出错。
  8. 你在循环结束时调用了 matrix,但你没有将它存储在任何地方,所以整个循环实际上没有做任何事情。
  9. 您正在尝试 rbind 最后一行中名为 matrix 的对象
  10. 数学运算符、逗号和变量之间缺少空格会降低代码的可读性和调试难度。我不只是说这是一种文体观点;这是我经常在 SO 上看到的主要错误来源。