Skip to contents

Recomputes every metric from the counts, so a caller never has to trust a rounded sensitivity column or worry whether a stored metric was on the 0-1 or the 0-100 scale.

Usage

diagnostic_metrics(
  tp,
  fn,
  fp,
  tn,
  ci = c("wilson", "exact", "none"),
  conf_level = 0.95,
  ba_method = c("auto", "wilson", "exact", "wald")
)

Arguments

tp, fn, fp, tn

Counts of true positives, false negatives, false positives and true negatives. Vectorised and recycled together.

ci

"wilson" (default), "exact" for Clopper-Pearson, or "none". Applies to the proportions and, through ba_ci, to balanced accuracy: asking for exact intervals gets exact intervals everywhere they are defined. Likelihood ratios always use lr_ci.

conf_level

Confidence level.

ba_method

Interval method for balanced accuracy: "auto" (default) follows ci, so ci = "exact" square-and-adds Clopper-Pearson components and ci = "wilson" square-and-adds Wilson ones. Set "wald" for the analytic normal-approximation variance, which is degenerate at a boundary – see ba_ci. With ci = "none" no balanced-accuracy interval is computed either.

Value

A data frame with one row per input. Proportions (sensitivity, specificity, ppv, npv, accuracy, ba, prevalence) are on the 0-1 scale; lr_pos and lr_neg are unbounded ratios, kappa can be negative, and pct_agreement is a percentage: the four counts, n, n_pos, n_neg, prevalence, then sensitivity, specificity, ppv, npv, accuracy and ba each with _lo and _hi, then lr_pos, lr_neg and kappa with intervals, and pct_agreement.

Examples

diagnostic_metrics(tp = 80, fn = 20, fp = 10, tn = 90)
#>   tp fn fp tn   n n_pos n_neg prevalence sensitivity sensitivity_lo
#> 1 80 20 10 90 200   100   100        0.5         0.8      0.7111708
#>   sensitivity_hi specificity specificity_lo specificity_hi       ppv    ppv_lo
#> 1      0.8666331         0.9      0.8256343      0.9447709 0.8888889 0.8074221
#>      ppv_hi       npv    npv_lo    npv_hi accuracy accuracy_lo accuracy_hi   ba
#> 1 0.9385168 0.8181818 0.7357859 0.8791043     0.85   0.7939442   0.8928641 0.85
#>       ba_lo     ba_hi lr_pos lr_pos_lo lr_pos_hi    lr_neg lr_neg_lo lr_neg_hi
#> 1 0.7920758 0.8901385      8   4.40765  14.52021 0.2222222 0.1493478 0.3306557
#>   kappa  kappa_lo  kappa_hi pct_agreement
#> 1   0.7 0.6010267 0.7989733            85
diagnostic_metrics(tp = 2, fn = 4, fp = 1, tn = 176, ci = "exact")
#>   tp fn fp  tn   n n_pos n_neg prevalence sensitivity sensitivity_lo
#> 1  2  4  1 176 183     6   177 0.03278689   0.3333333     0.04327187
#>   sensitivity_hi specificity specificity_lo specificity_hi       ppv     ppv_lo
#> 1      0.7772219   0.9943503      0.9689253       0.999857 0.6666667 0.09429932
#>      ppv_hi       npv    npv_lo    npv_hi  accuracy accuracy_lo accuracy_hi
#> 1 0.9915962 0.9777778 0.9440823 0.9939128 0.9726776   0.9373934   0.9910702
#>          ba    ba_lo     ba_hi lr_pos lr_pos_lo lr_pos_hi    lr_neg lr_neg_lo
#> 1 0.6638418 0.518255 0.8858032     59  6.166713  564.4823 0.6704545 0.3807161
#>   lr_neg_hi     kappa    kappa_lo  kappa_hi pct_agreement
#> 1  1.180694 0.4320298 -0.05896072 0.9230203      97.26776

# A perfect two-by-two still has an interval, because 183 observations are
# not infinite information.
diagnostic_metrics(tp = 6, fn = 0, fp = 0, tn = 177,
                   ci = "exact")[, c("ba", "ba_lo", "ba_hi")]
#>   ba     ba_lo ba_hi
#> 1  1 0.7701395     1