ordered is a parsnip extension to enable additional classification models for ordinal outcomes (e.g., “low”, “medium”, “high”). While there are several model/engine combinations in the parsnip package that can be used, this package adds:
MASS::polr()
ordinal::clm() (Christensen,
2023)VGAM::vglm() and VGAM::vgam() (Yee,
2015)ordinalNet::ordinalNet() (Wurm, Hanlon, and Rathouz,
2021)rms::lrm() and rms::orm() (Harrell,
2015)glmnetcr::glmnetcr() (Archer and Williams,
2012)rpartScore::rpartScore()
(Galimberti, Soffritti, and Di Maso,
2012)ordinalForest::ordfor()
(Hornung, 2020)orf::orf() (Lechner and
Okasa, 2025)Some features in other tidymodels packages are useful for ordinal outcomes:
parsnip::decision_tree() and parsnip::rand_forest(), provided
by bonsai, use the ordinal nature of
ordered factors to train the model, yielding different fits than for
unordered factors.yardstick::kap() for weighted and unweighted Kappa statistics (the
former being of more interest). Also,
yardstick::classification_cost() can utilize more complex cost
structures and uses the class probabilities for estimation.You can install the latest released version of ordered from CRAN via
install.packages("ordered")
and the development version of ordered from GitHub via
# install.packages("pak")
# pak::pak("corybrunson/ordered")
install.packages("ordered", repos = c('https://corybrunson.r-universe.dev', 'https://cloud.r-project.org'))
or
# install.packages("remotes")
# remotes::install_github("corybrunson/ordered")
install.packages("ordered", repos = c('https://corybrunson.r-universe.dev', 'https://cloud.r-project.org'))
ordered provides new engines for several models, including all engines
for ordinal_reg():
| model | engine | class | prob | linear_pred |
|---|---|---|---|---|
decision_tree |
rpartScore |
✔ | ✖ | ✖ |
gen_additive_mod |
vgam |
✔ | ✔ | ✔ |
ordinal_reg |
polr |
✔ | ✔ | ✖ |
ordinal_reg |
clm |
✔ | ✔ | ✔ |
ordinal_reg |
lrm |
✔ | ✔ | ✔ |
ordinal_reg |
orm |
✔ | ✔ | ✔ |
ordinal_reg |
vglm |
✔ | ✔ | ✔ |
ordinal_reg |
ordinalNet |
✔ | ✔ | ✔ |
ordinal_reg |
glmnetcr |
✔ | ✔ | ✖ |
rand_forest |
ordinalForest |
✔ | ✔ | ✖ |
rand_forest |
orf |
✔ | ✔ | ✖ |
ordinal_reg recognizes several tunable arguments shared by at least
two engines in ordered:
| engine | ordinal_link | odds_link | threshold_structure | parallel_reg | penalty | mixture |
|---|---|---|---|---|---|---|
polr |
✔ | ✖ | ✖ | ✖ | ✖ | ✖ |
clm |
✔ | ✖ | ✔ | ✔ | ✖ | ✖ |
lrm |
✖ | ✖ | ✖ | ✖ | ✔ | ✖ |
orm |
✔ | ✖ | ✖ | ✖ | ✔ | ✖ |
vglm |
✔ | ✔ | ✔ | ✔ | ✖ | ✖ |
ordinalNet |
✔ | ✔ | ✖ | ✔ | ✔ | ✔ |
glmnetcr |
✖ | ✖ | ✖ | ✖ | ✔ | ✔ |
Here is a simple example using computational chemistry data to predict the permeability of a molecule:
library(dplyr)
library(ordered)
data(caco, package = "QSARdata")
caco_dat <-
inner_join(caco_Outcome, caco_Dragon, by = "Molecule") %>%
as_tibble() %>%
select(
class = Class,
mol_weight = QikProp_mol_MW,
volume = QikProp_volume,
ClogP
)
caco_train <- caco_dat[-(1:10), ]
caco_test <- caco_dat[ (1:10), ]
ord_rf_spec <-
# you should really use many more trees and score sets
rand_forest(mtry = 2, trees = 100) %>%
set_mode("classification") %>%
set_engine("ordinalForest", nsets = 100)
set.seed(382)
ord_rf_fit <- ord_rf_spec %>% fit(class ~ ., data = caco_train)
augment(ord_rf_fit, new_data = caco_test)
#> # A tibble: 10 × 8
#> .pred_class .pred_L .pred_M .pred_H class mol_weight volume ClogP
#> <ord> <dbl> <dbl> <dbl> <ord> <dbl> <dbl> <dbl>
#> 1 L 0.374 0.368 0.258 M 123. 445. 0.799
#> 2 M 0.289 0.512 0.199 L 290. 856. 0.534
#> 3 M 0.170 0.809 0.0212 M 519. 1576. 1.02
#> 4 M 0.209 0.740 0.0503 M 533. 1606. 1.58
#> 5 M 0.126 0.762 0.113 M 505. 1517. 1.71
#> 6 M 0.0657 0.917 0.0176 M 519. 1547. 2.27
#> 7 M 0.213 0.747 0.0401 M 517. 1600. 1.78
#> 8 M 0.111 0.859 0.0306 M 531. 1631. 2.34
#> 9 M 0.0403 0.932 0.0277 M 517. 1572. 2.81
#> 10 L 0.569 0.428 0.003 L 588. 1799. -1.85
Please note that the ordered project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.
To voice support for or volunteer to contribute additional engines, please comment on this issue.
Jason Cory Brunson was supported in part by NIH/NIDCD R01DC022733.