set.seed(1234) N = 2500 x = rnorm(N) lp = 0 + .5*x y = rbinom(N, size = 1, prob = plogis(lp)) model = glm(y ~ x, family = binomial) predict_class = predict(model) > 0
library(confusionMatrix) confusion_matrix(predict_class, y)
$Accuracy
# A tibble: 1 x 5
Accuracy `Accuracy LL` `Accuracy UL` `Accuracy Guessing` `Accuracy P-value`
<dbl> <dbl> <dbl> <dbl> <dbl>
1 0.591 0.572 0.611 0.513 2.88e-15
$Other
# A tibble: 1 x 19
Positive N `N Positive` `N Negative` `Sensitivity/Re… `Specificity/TN…
<chr> <int> <int> <int> <dbl> <dbl>
1 0 2500 1283 1217 0.634 0.546
# … with 13 more variables: `PPV/Precision` <dbl>, NPV <dbl>, `F1/Dice` <dbl>,
# Prevalence <dbl>, `Detection Rate` <dbl>, `Detection Prevalence` <dbl>,
# `Balanced Accuracy` <dbl>, FDR <dbl>, FOR <dbl>, `FPR/Fallout` <dbl>,
# FNR <dbl>, `D Prime` <dbl>, AUC <dbl>
$`Association and Agreement`
# A tibble: 1 x 6
Kappa `Adjusted Rand` Yule Phi Peirce Jaccard
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.180 0.0329 0.351 0.181 0.180 0.394
Works for the multi-class setting too, but not all statistics are applicable/available. Note that the ‘Other’ statistics are provided for each class, as well as averaged.
p_multi = sample(letters[1:4], 250, replace = TRUE, prob = 1:4) o_multi = sample(letters[1:4], 250, replace = TRUE, prob = 1:4) confusion_matrix(p_multi, o_multi)
Warning in calc_agreement(conf_mat): Some association metrics may not be
calculated due to lack of 2x2 table
$Accuracy
# A tibble: 1 x 5
Accuracy `Accuracy LL` `Accuracy UL` `Accuracy Guessing` `Accuracy P-value`
<dbl> <dbl> <dbl> <dbl> <dbl>
1 0.344 0.285 0.406 0.388 0.933
$Other
# A tibble: 5 x 17
Class N `Sensitivity/Re… `Specificity/TN… `PPV/Precision` NPV `F1/Dice`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 a 24 0.0833 0.907 0.0870 0.903 0.0851
2 b 54 0.278 0.806 0.283 0.802 0.280
3 c 75 0.333 0.714 0.333 0.714 0.333
4 d 97 0.454 0.641 0.444 0.649 0.449
5 Aver… 62.5 0.287 0.767 0.287 0.767 0.287
# … with 10 more variables: Prevalence <dbl>, `Detection Rate` <dbl>,
# `Detection Prevalence` <dbl>, `Balanced Accuracy` <dbl>, FDR <dbl>,
# FOR <dbl>, `FPR/Fallout` <dbl>, FNR <dbl>, `D Prime` <dbl>, AUC <dbl>
$`Association and Agreement`
# A tibble: 1 x 6
Kappa `Adjusted Rand` Yule Phi Peirce Jaccard
<dbl> <dbl> <lgl> <lgl> <lgl> <lgl>
1 0.0652 0.0000361 NA NA NA NA
In wide format, you have a simple way to pluck any particular statistic.
cm = confusion_matrix(predict_class, y) cm[['Other']][['N']]
[1] 2500
cm[['Association and Agreement']][['Yule']]
[1] 0.3514883
However, if you want to present a lot of statistics, a longer format might be more ideal.
confusion_matrix(predict_class, y, longer = TRUE)
$Accuracy
# A tibble: 5 x 2
Statistic Value
<chr> <dbl>
1 Accuracy 5.91e- 1
2 Accuracy LL 5.72e- 1
3 Accuracy UL 6.11e- 1
4 Accuracy Guessing 5.13e- 1
5 Accuracy P-value 2.88e-15
$Other
# A tibble: 18 x 3
Positive Statistic Value
<chr> <chr> <dbl>
1 0 N 2500
2 0 N Positive 1283
3 0 N Negative 1217
4 0 Sensitivity/Recall/TPR 0.634
5 0 Specificity/TNR 0.546
6 0 PPV/Precision 0.595
7 0 NPV 0.586
8 0 F1/Dice 0.614
9 0 Prevalence 0.513
10 0 Detection Rate 0.326
11 0 Detection Prevalence 0.547
12 0 Balanced Accuracy 0.590
13 0 FDR 0.405
14 0 FOR 0.414
15 0 FPR/Fallout 0.454
16 0 FNR 0.366
17 0 D Prime 0.458
18 0 AUC 0.627
$`Association and Agreement`
# A tibble: 6 x 2
Statistic Value
<chr> <dbl>
1 Kappa 0.180
2 Adjusted Rand 0.0329
3 Yule 0.351
4 Phi 0.181
5 Peirce 0.180
6 Jaccard 0.394
Either way, the tibble output will work nicely with various packages for formatting tables.