【问题标题】:Create multiple confusion matrices in R using loops使用循环在 R 中创建多个混淆矩阵
【发布时间】:2021-03-25 15:22:08
【问题描述】:

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

所以对于下面的数据框,我想要一个混淆矩阵,用于何时 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

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

【问题讨论】:

    标签: r loops while-loop confusion-matrix


    【解决方案1】:

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

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

    【讨论】:

    • 非常感谢您的详尽回答和解释!我不熟悉sapply,所以我做了一些阅读。我将来会为其他人添加此评论,我还希望有一个标记为Age 的列并将年龄列为行,因此我将final 转换为数据框,然后执行setDT(final, keep.rownames = "Age")
    猜你喜欢
    • 2021-10-30
    • 2021-03-02
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-28
    • 2011-06-21
    相关资源
    最近更新 更多