Skip to contents

classbound is designed to work with the widest possible range of R classifiers. This vignette explains how prediction routing works and how to handle classifiers whose APIs do not fit the default path.

The prediction philosophy

Standard classifier (predict returns factor/vector)
    → handled automatically via predict_adapter.default()

Non-standard classifier (predict returns a list or complex object)
    → provide predfun to extract class labels

Officially supported classifiers (rpart, randomForest, PPtree, ppforest2)
    → handled by built-in S3 adapters with full probability support

1. Standard classifiers (no extra work needed)

If a classifier’s predict() method returns a vector or factor of class labels directly, classbound handles it automatically. No configuration is needed.

library(classbound)
library(palmerpenguins)
penguins <- na.omit(palmerpenguins::penguins[
  ,
  c("species", "bill_length_mm", "bill_depth_mm")
])

# e1071::svm returns a factor of class labels; works out of the box
classbound(penguins, species ~ bill_length_mm + bill_depth_mm, e1071::svm)

2. Non-standard models (using predfun)

Some classifiers return a list, data frame, or other complex object from predict(). The default path will stop with an informative error message suggesting you provide a predfun. The predfun receives the fitted model and new data, and must return either a factor/vector of class labels, or a list with $class and $probs.

# MASS::qda returns list($class, $posterior, $x), so extract $class
classbound(
  penguins,
  species ~ bill_length_mm + bill_depth_mm,
  MASS::qda,
  predfun = function(model, newdata, ...) predict(model, newdata, ...)$class
)

# MASS::lda (same approach)
classbound(
  penguins,
  species ~ bill_length_mm + bill_depth_mm,
  MASS::lda,
  predfun = function(model, newdata, ...) predict(model, newdata, ...)$class
)

# Return probabilities as well (enables gradient visualization)
classbound(
  penguins,
  species ~ bill_length_mm + bill_depth_mm,
  MASS::lda,
  predfun = function(model, newdata, ...) {
    out <- predict(model, newdata, ...)
    list(class = out$class, probs = out$posterior)
  }
)

The predfun argument is available in classbound(), fit_model() (via boundary_compute()), and predict_model().

3. Officially supported classifiers (built-in adapters)

classbound maintains a small set of built-in S3 adapters for classifiers whose APIs require model-specific handling to extract both class labels and probabilities:

Classifier Adapter Probabilities
rpart::rpart predict_adapter.rpart Yes
randomForest::randomForest predict_adapter.randomForest Yes
PPtreeViz::PPTreeclass predict_adapter.PPtreeclass No
PPtreeExt::PPtreeExtclass predict_adapter.PPtreeExtclass No
ppforest2::pprf predict_adapter.pprf_classification Yes

These adapters are invoked automatically when the classifier object belongs to the corresponding S3 class. No predfun is needed.

The adapter contract

Every prediction path must produce a list with exactly two elements:

list(
  class = factor(...),  # vector of predicted class labels
  probs = matrix(...)   # n x K probability matrix, or NULL
)

probs must be NULL for classifiers that do not provide probability estimates. classbound handles NULL probabilities gracefully: the boundary plot renders with flat (non-gradient) colored regions instead of a probability surface.

4. Writing a custom S3 adapter

Custom S3 adapters are only needed if you are building an extension package for classbound and want to officially support a complex classifier without requiring users to write predfun every time.

For most users, a predfun is sufficient and far simpler.

# Example: custom adapter for a hypothetical classifier "myModel"
predict_adapter.myModel <- function(model, newdata, ...) {
  raw <- predict(model, newdata, type = "response")
  list(
    class = factor(raw$labels),
    probs = as.matrix(raw$probabilities)
  )
}

Define the method in your package’s namespace and it will be dispatched automatically whenever classbound encounters a model object of class "myModel".