Closed stephenturner closed 3 years ago
another option besides caret
:
https://github.com/m-clark/confusionMatrix/
usage:
devtools::install_github('m-clark/confusionMatrix')
library(confusionMatrix)
library(tidyverse)
pred <-
c(rep("first", 48),
rep("second",55),
rep("third",41),
rep("unrelated", 56))
truth <-
c(rep("first",50),
rep("second",50),
rep("third",50),
rep("unrelated",50))
confusion_matrix(
prediction = pred,
target = truth,
return_table = TRUE
) %>%
purrr::pluck("Other") %>%
gather(Measure, Value, -Class,-N) %>%
select(-N) %>%
spread(Class, Value) %>%
knitr::kable()
Measure | Average | first | second | third | unrelated |
---|---|---|---|---|---|
AUC | 0.9999780 | 0.9999968 | 0.9999978 | 0.9999205 | 0.9999969 |
Balanced Accuracy | 0.9633333 | 0.9800000 | 0.9833333 | 0.9100000 | 0.9800000 |
D Prime | 6.3160772 | 6.5040988 | 6.5873255 | 5.6687856 | 6.5040988 |
Detection Prevalence | 0.2500000 | 0.2400000 | 0.2750000 | 0.2050000 | 0.2800000 |
Detection Rate | 0.2362500 | 0.2400000 | 0.2500000 | 0.2050000 | 0.2500000 |
F1/Dice | 0.9441170 | 0.9795918 | 0.9523810 | 0.9010989 | 0.9433962 |
FDR | 0.0495130 | 0.0000000 | 0.0909091 | 0.0000000 | 0.1071429 |
FNR | 0.0550000 | 0.0400000 | 0.0000000 | 0.1800000 | 0.0000000 |
FOR | 0.0174404 | 0.0131579 | 0.0000000 | 0.0566038 | 0.0000000 |
FPR/Fallout | 0.0183333 | 0.0000000 | 0.0333333 | 0.0000000 | 0.0400000 |
NPV | 0.9825596 | 0.9868421 | 1.0000000 | 0.9433962 | 1.0000000 |
PPV/Precision | 0.9504870 | 1.0000000 | 0.9090909 | 1.0000000 | 0.8928571 |
Prevalence | 0.2500000 | 0.2500000 | 0.2500000 | 0.2500000 | 0.2500000 |
Sensitivity/Recall/TPR | 0.9450000 | 0.9600000 | 1.0000000 | 0.8200000 | 1.0000000 |
Specificity/TNR | 0.9816667 | 1.0000000 | 0.9666667 | 1.0000000 | 0.9600000 |
pros:
dplyr
cons:
@stephenturner what do you think?
Nice find. Looking through the code there isn't a whole lot of complex stuff going on here. I might just copy all the functions into a single .R file in skater.
I still have some work to do here, but I've taken the code from m-clark/confusion_matrix, cut out the stuff we don't want (the agreement calculations, and the stats that throw errors), credited m-clark, and added a contingency table to the returned output. Demonstration below, pulling out the contingency table, and outputting in long format then re-widening. PR in #27
cc @vpnagraj @genignored
library(skater)
prediction = c(rep(1, 50), rep(2, 40), rep(3, 60))
target = c(rep(1, 50), rep(2, 50), rep(3, 50))
confusion_matrix(prediction, target)
#> $Accuracy
#> # A tibble: 1 x 5
#> Accuracy `Accuracy LL` `Accuracy UL` `Accuracy Guessing` `Accuracy P-value`
#> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0.933 0.881 0.968 0.333 3.36e-54
#>
#> $Other
#> # A tibble: 4 x 15
#> Class N `Sensitivity/Re… `Specificity/TN… `PPV/Precision` NPV `F1/Dice`
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 50 1 1 1 1 1
#> 2 2 50 0.8 1 1 0.909 0.889
#> 3 3 50 1 0.9 0.833 1 0.909
#> 4 Aver… 50 0.933 0.967 0.944 0.970 0.933
#> # … with 8 more variables: Prevalence <dbl>, `Detection Rate` <dbl>, `Detection
#> # Prevalence` <dbl>, `Balanced Accuracy` <dbl>, FDR <dbl>, FOR <dbl>,
#> # `FPR/Fallout` <dbl>, FNR <dbl>
#>
#> $Table
#> Target
#> Predicted 1 2 3
#> 1 50 0 0
#> 2 0 40 0
#> 3 0 10 50
confusion_matrix(prediction, target) %>% purrr::pluck("Table")
#> Target
#> Predicted 1 2 3
#> 1 50 0 0
#> 2 0 40 0
#> 3 0 10 50
confusion_matrix(prediction, target, longer=TRUE)
#> $Accuracy
#> # A tibble: 5 x 2
#> Statistic Value
#> <chr> <dbl>
#> 1 Accuracy 9.33e- 1
#> 2 Accuracy LL 8.81e- 1
#> 3 Accuracy UL 9.68e- 1
#> 4 Accuracy Guessing 3.33e- 1
#> 5 Accuracy P-value 3.36e-54
#>
#> $Other
#> # A tibble: 56 x 3
#> Class Statistic Value
#> <chr> <chr> <dbl>
#> 1 1 N 50
#> 2 1 Sensitivity/Recall/TPR 1
#> 3 1 Specificity/TNR 1
#> 4 1 PPV/Precision 1
#> 5 1 NPV 1
#> 6 1 F1/Dice 1
#> 7 1 Prevalence 0.333
#> 8 1 Detection Rate 0.333
#> 9 1 Detection Prevalence 0.333
#> 10 1 Balanced Accuracy 1
#> # … with 46 more rows
#>
#> $Table
#> Target
#> Predicted 1 2 3
#> 1 50 0 0
#> 2 0 40 0
#> 3 0 10 50
confusion_matrix(prediction, target, longer=TRUE) %>%
purrr::pluck("Other") %>%
tidyr::spread(Class, Value)
#> # A tibble: 14 x 5
#> Statistic `1` `2` `3` Average
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 Balanced Accuracy 1 0.9 0.95 0.95
#> 2 Detection Prevalence 0.333 0.267 0.4 0.333
#> 3 Detection Rate 0.333 0.267 0.333 0.311
#> 4 F1/Dice 1 0.889 0.909 0.933
#> 5 FDR 0 0 0.167 0.0556
#> 6 FNR 0 0.200 0 0.0667
#> 7 FOR 0 0.0909 0 0.0303
#> 8 FPR/Fallout 0 0 0.100 0.0333
#> 9 N 50 50 50 50
#> 10 NPV 1 0.909 1 0.970
#> 11 PPV/Precision 1 1 0.833 0.944
#> 12 Prevalence 0.333 0.333 0.333 0.333
#> 13 Sensitivity/Recall/TPR 1 0.8 1 0.933
#> 14 Specificity/TNR 1 1 0.9 0.967
caret has a nice confusion matrix function (source code). Prints lots of useful stats on each class, as well as overall stats. Example below.
The caret package has a ton of dependencies, and the
confusionMatrix()
function itself requires several of the additional dependencies inSuggests
. It can be finicky to install on any OS, and I'd rather not include it as a dependency.Can we pull out the useful bits from the source code, or else find another lighter weight function elsewhere we can copy over that could give us similar stats/functionality?
cc @vpnagraj