【问题标题】:Plot confusion matrix in R using ggplot使用 ggplot 在 R 中绘制混淆矩阵
【发布时间】:2016-10-20 05:13:13
【问题描述】:

我有两个混淆矩阵,其计算值为真阳性(tp)、假阳性(fp)、真阴性(tn)和假阴性(fn),对应于两种不同的方法。我想将它们表示为

我相信 facet grid 或 facet wrap 可以做到这一点,但我觉得很难开始。 这里是method1和method2对应的两个混淆矩阵的数据

dframe<-structure(list(label = structure(c(4L, 2L, 1L, 3L, 4L, 2L, 1L, 
3L), .Label = c("fn", "fp", "tn", "tp"), class = "factor"), value = c(9, 
0, 3, 1716, 6, 3, 6, 1713), method = structure(c(1L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L), .Label = c("method1", "method2"), class = "factor")), .Names = c("label", 
"value", "method"), row.names = c(NA, -8L), class = "data.frame")

【问题讨论】:

    标签: r ggplot2 confusion-matrix


    【解决方案1】:

    这是一个非常古老的问题,但使用 ggplot2 似乎有一个非常直接的解决方案,但尚未提及。

    希望对某人有所帮助:

    cm <- confusionMatrix(factor(y.pred), factor(y.test), dnn = c("Prediction", "Reference"))
    
    plt <- as.data.frame(cm$table)
    plt$Prediction <- factor(plt$Prediction, levels=rev(levels(plt$Prediction)))
    
    ggplot(plt, aes(Prediction,Reference, fill= Freq)) +
            geom_tile() + geom_text(aes(label=Freq)) +
            scale_fill_gradient(low="white", high="#009194") +
            labs(x = "Reference",y = "Prediction") +
            scale_x_discrete(labels=c("Class_1","Class_2","Class_3","Class_4")) +
            scale_y_discrete(labels=c("Class_4","Class_3","Class_2","Class_1"))
    

    【讨论】:

    • 我喜欢你的回答。
    • 标签向后
    • @Frank 感谢您指出这一点。我已经对帖子进行了编辑 - 现在应该可以正确反转级别了。
    【解决方案2】:

    这是一个使用cvms包的reprex,即ggplot2的包装函数来制作混淆矩阵。

    library(cvms)
    library(broom)    
    library(tibble)   
    library(ggimage)   
    #> Loading required package: ggplot2
    library(rsvg)   
    
    set.seed(1)
    d_multi <- tibble("target" = floor(runif(100) * 3),
                      "prediction" = floor(runif(100) * 3))
    conf_mat <- confusion_matrix(targets = d_multi$target,
                                 predictions = d_multi$prediction)
    
    # plot_confusion_matrix(conf_mat$`Confusion Matrix`[[1]], add_sums = TRUE)
    plot_confusion_matrix(
      conf_mat$`Confusion Matrix`[[1]],
      add_sums = TRUE,
      sums_settings = sum_tile_settings(
        palette = "Oranges",
        label = "Total",
        tc_tile_border_color = "black"
      )
    )
    

    reprex package (v0.3.0) 于 2021-01-19 创建

    【讨论】:

      【解决方案3】:

      基于 MYaseen208 的答案的稍微模块化的解决方案。对于大型数据集/多项式分类可能更有效:

      confusion_matrix <- as.data.frame(table(predicted_class, actual_class))
      
      ggplot(data = confusion_matrix
             mapping = aes(x = Var1,
                           y = Var2)) +
        geom_tile(aes(fill = Freq)) +
        geom_text(aes(label = sprintf("%1.0f", Freq)), vjust = 1) +
        scale_fill_gradient(low = "blue",
                            high = "red",
                            trans = "log") # if your results aren't quite as clear as the above example
      

      【讨论】:

        【解决方案4】:

        这是另一个基于 ggplot2 的选项;首先是数据(来自插入符号):

        library(caret)
        
        # data/code from "2 class example" example courtesy of ?caret::confusionMatrix
        
        lvs <- c("normal", "abnormal")
        truth <- factor(rep(lvs, times = c(86, 258)),
                        levels = rev(lvs))
        pred <- factor(
          c(
            rep(lvs, times = c(54, 32)),
            rep(lvs, times = c(27, 231))),
          levels = rev(lvs))
        
        confusionMatrix(pred, truth)
        

        并构建绘图(在设置“表格”时根据需要在下面替换您自己的矩阵):

        library(ggplot2)
        library(dplyr)
        
        table <- data.frame(confusionMatrix(pred, truth)$table)
        
        plotTable <- table %>%
          mutate(goodbad = ifelse(table$Prediction == table$Reference, "good", "bad")) %>%
          group_by(Reference) %>%
          mutate(prop = Freq/sum(Freq))
        
        # fill alpha relative to sensitivity/specificity by proportional outcomes within reference groups (see dplyr code above as well as original confusion matrix for comparison)
        ggplot(data = plotTable, mapping = aes(x = Reference, y = Prediction, fill = goodbad, alpha = prop)) +
          geom_tile() +
          geom_text(aes(label = Freq), vjust = .5, fontface  = "bold", alpha = 1) +
          scale_fill_manual(values = c(good = "green", bad = "red")) +
          theme_bw() +
          xlim(rev(levels(table$Reference)))
        

        # note: for simple alpha shading by frequency across the table at large, simply use "alpha = Freq" in place of "alpha = prop" when setting up the ggplot call above, e.g.,
        ggplot(data = plotTable, mapping = aes(x = Reference, y = Prediction, fill = goodbad, alpha = Freq)) +
          geom_tile() +
          geom_text(aes(label = Freq), vjust = .5, fontface  = "bold", alpha = 1) +
          scale_fill_manual(values = c(good = "green", bad = "red")) +
          theme_bw() +
          xlim(rev(levels(table$Reference)))
        

        【讨论】:

        • 如果您将Reference 更改为truth 并将Prediction 更改为response,则此代码适用于mlr3 包的输出。
        【解决方案5】:

        老问题,但我写了这个函数,我认为它是一个更漂亮的答案。产生不同的调色板(或任何你想要的,但默认是不同的):

        prettyConfused<-function(Actual,Predict,colors=c("white","red4","dodgerblue3"),text.scl=5){
          actual = as.data.frame(table(Actual))
          names(actual) = c("Actual","ActualFreq")
        
          #build confusion matrix
          confusion = as.data.frame(table(Actual, Predict))
          names(confusion) = c("Actual","Predicted","Freq")
        
          #calculate percentage of test cases based on actual frequency
        
          confusion = merge(confusion, actual, by=c('Actual','Actual'))
          confusion$Percent = confusion$Freq/confusion$ActualFreq*100
          confusion$ColorScale<-confusion$Percent*-1
          confusion[which(confusion$Actual==confusion$Predicted),]$ColorScale<-confusion[which(confusion$Actual==confusion$Predicted),]$ColorScale*-1
          confusion$Label<-paste(round(confusion$Percent,0),"%, n=",confusion$Freq,sep="")
          tile <- ggplot() +
            geom_tile(aes(x=Actual, y=Predicted,fill=ColorScale),data=confusion, color="black",size=0.1) +
            labs(x="Actual",y="Predicted")
        
          tile = tile +
                geom_text(aes(x=Actual,y=Predicted, label=Label),data=confusion, size=text.scl, colour="black") +
                scale_fill_gradient2(low=colors[2],high=colors[3],mid=colors[1],midpoint = 0,guide='none')
        }
        

        【讨论】:

          【解决方案6】:

          这可能是一个好的开始

          library(ggplot2)
          ggplot(data =  dframe, mapping = aes(x = label, y = method)) +
            geom_tile(aes(fill = value), colour = "white") +
            geom_text(aes(label = sprintf("%1.0f",value)), vjust = 1) +
            scale_fill_gradient(low = "white", high = "steelblue")
          

          已编辑

          TClass <- factor(c(0, 0, 1, 1))
          PClass <- factor(c(0, 1, 0, 1))
          Y      <- c(2816, 248, 34, 235)
          df <- data.frame(TClass, PClass, Y)
          
          library(ggplot2)
          ggplot(data =  df, mapping = aes(x = TClass, y = PClass)) +
            geom_tile(aes(fill = Y), colour = "white") +
            geom_text(aes(label = sprintf("%1.0f", Y)), vjust = 1) +
            scale_fill_gradient(low = "blue", high = "red") +
            theme_bw() + theme(legend.position = "none")
          

          【讨论】:

            猜你喜欢
            • 2016-01-31
            • 2021-07-21
            • 1970-01-01
            • 1970-01-01
            • 2020-07-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多