ordered

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:

Some features in other tidymodels packages are useful for ordinal outcomes:

Installation

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'))

Available models, engines, and prediction types

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 ✔ ✔ ✖

Tunable model arguments

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 ✖ ✖ ✖ ✖ ✔ ✔

Example

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

Code of Conduct

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.

Acknowledgments

Jason Cory Brunson was supported in part by NIH/NIDCD R01DC022733.