Breaking changes for ordered predictors in upcoming pROC 1.20.0

pROC has always accepted ordered factors as predictors (for example aSAH$wfns, the WFNS neurological grade in the aSAH dataset, with levels 1 to 5). Internally it simply called as.numeric() on them and computed thresholds as the midpoints between consecutive numeric codes (1.5, 2.5, and so on).

That's reasonable when the levels happen to be the numbers 1:n, but it is not appropriate for an ordered factor whose levels are textual, for example "very low", "low", "medium", "high", "very high". The thresholds were still -Inf, 1.5, 2.5, 3.5, 4.5, Inf, numbers that do not correspond to anything in the data and are meaningless to show. This was reported as issue #63, and a fix for it was just merged into the develop branch.

In practice, this could potentially break some of your code. Before it reaches CRAN, I'd like testers who use ordered predictors to try the develop version on their own data and tell me if anything looks wrong.

What changes

On develop, thresholds of an ordered ROC curve are now the predictor's own levels, plus one infinite sentinel for the all-positive or all-negative cut-off. Sensitivities, specificities and AUC are exactly the same as before, only the threshold labels change, from numeric midpoints to the levels you actually gave it:

library(pROC)
data(aSAH)

wfns.txt <- aSAH$wfns
levels(wfns.txt) <- c("very low", "low", "medium", "high", "very high")

r <- roc(aSAH$outcome, wfns.txt, quiet = TRUE)
r$thresholds
# very low, low, medium, high, very high, Inf
# Levels: very low < low < medium < high < very high < Inf

coords(r, "medium")
#   threshold specificity sensitivity
# 1    medium   0.7916667   0.6585365

This is a breaking change for any code that reads roc$thresholds as numbers, or passes a numeric cut-off into coords(), ci.thresholds(), ci.coords(), or plot.roc(print.thres = ...) on an ordered ROC curve. Numeric predictors are entirely unaffected by this change. Where you used to pass a midpoint, pass the level label instead:

# Incorrect (pROC <= 1.19.1 converted wfns to 1:5, thresholds were midpoints):
coords(roc(aSAH$outcome, aSAH$wfns), 2.5)

# Correct: pass the level label
coords(roc(aSAH$outcome, aSAH$wfns, quiet = TRUE), "3")

The mapping from old midpoints to new labels is straightforward (for direction = "<", the default): the old -Inf becomes the lowest level, the old midpoint k + 0.5 becomes the level in position k + 1, and the old Inf becomes the level literally named "Inf".

As a side effect of the same fix, ci.coords(..., x = "best", best.policy = "omit") now correctly drops a bootstrap replicate that has several equally-good "best" points, instead of silently keeping the first one.

How to test it

This is not released yet: it is only on the develop branch, ahead of the next CRAN release, planned for early 2027. If you use ordered predictors with roc(), please install the development version and run your own code against it:

if (! requireNamespace("devtools")) install.packages("devtools")
devtools::install_github("xrobin/pROC@develop")

Recommendations

If you have scripts or packages that build ROC curves from ordered predictors, please run them against the develop version and check the following:

If anything looks off, please comment on issue #63 or open a new issue on GitHub before this reaches CRAN. Thanks in advance for testing!

Xavier Robin
Publié le mardi 6 octobre 2026 à 14:26 CEST
Lien permanent : /blog/2026/10/06/breaking-changes-for-ordered-predictors-in-upcoming-proc-1.20.0
Tags : pROC
Commentaires : 0

Switch to English

Chercher

Tags

Bruit de fond Hobbys Humour Informatique Internet Livres Logiciels Moi Mon site web Mozilla Photo Politique Programmation Scolaire Ubuntu pROC

Billets récents

Calendrier

lun.mar.mer.jeu.ven.sam.dim.
1234
567891011
12131415161718
19202122232425
262728293031

Syndication