classbound is an R package for exploring and comparing classification
decision boundaries. It provides a unified interface for fitting
classifiers, computing 2D boundary grids, and visualizing how different
models partition the feature space.
What you can do with classbound:
explorapp())tidymodels workflowsFull documentation: https://natydasilva.github.io/classbound/
devtools::install_github("natydasilva/classbound")
classbound() fits a model, computes its decision boundary, and plots
the result in a single call.
library(classbound)
library(palmerpenguins)
penguins <- na.omit(palmerpenguins::penguins[
,
c("species", "bill_length_mm", "bill_depth_mm")
])
classbound(
data = penguins,
formula = species ~ bill_length_mm + bill_depth_mm,
classifier = rpart::rpart
)

For full control, use the three-step pipeline:
# 1. Fit
model <- fit_model(penguins, species ~ bill_length_mm + bill_depth_mm, rpart::rpart)
# 2. Compute boundary
model <- boundary_compute(model)
# 3. Plot
plot_boundary(
model,
obs_data = penguins,
x_col = "bill_length_mm",
y_col = "bill_depth_mm",
true_label = "species"
)

boundary_compute() returns the model with the grid attached, so you
can replot with different settings without refitting.
Launch the built-in Shiny application for point-and-click exploration:
# Start with your own dataset
explorapp(data = penguins, target_col = "species")
# Or start empty and simulate/draw data
explorapp()
In explorapp() you can: - Import real data or simulate synthetic
datasets - Draw classification data by hand - Fit and compare multiple
classifiers simultaneously - Switch between 2D Slice and Projection
views for high-dimensional data - Inject outliers and observe how
boundaries shift - Inspect probability surfaces (for supported
classifiers) - Export data, models, plots, and a reproduce script
Use explorapp() to:
Use the core Classbound functions directly:
fit_model()
boundary_compute()
plot_boundary()
When a model is trained on more than two features, boundary_compute()
supports:
penguins3 <- na.omit(palmerpenguins::penguins[
,
c("species", "bill_length_mm", "bill_depth_mm", "flipper_length_mm")
])
m3 <- fit_model(penguins3, species ~ ., rpart::rpart)
m3_slice <- boundary_compute(m3,
feature_range = list(bill_length_mm = c(30, 60), bill_depth_mm = c(10, 25)),
resolution = 60
)
plot_boundary(m3_slice,
obs_data = penguins3,
x_col = "bill_length_mm", y_col = "bill_depth_mm",
true_label = "species"
)

feat_cols <- c("bill_length_mm", "bill_depth_mm", "flipper_length_mm")
pca <- prcomp(penguins3[, feat_cols], scale. = TRUE)
basis <- pca$rotation[, 1:2]
x_std <- scale(penguins3[, feat_cols], center = pca$center, scale = pca$scale)
z_mat <- x_std %*% basis
m3_proj <- boundary_compute(m3,
feature_range = list(
PC1 = range(z_mat[, 1]) + c(-0.5, 0.5),
PC2 = range(z_mat[, 2]) + c(-0.5, 0.5)
),
resolution = 60,
projection = list(basis = basis, center = pca$center, scale = pca$scale)
)
plot_boundary(m3_proj,
obs_data = penguins3,
x_col = "PC1", y_col = "PC2", true_label = "species"
)

See the high-dimensional guide for a full explanation.
library(parsnip)
library(workflowsets)
spec_tree <- decision_tree(mode = "classification") |> set_engine("rpart")
spec_rf <- rand_forest(mode = "classification") |> set_engine("randomForest")
wf_set <- workflow_set(
preproc = list(base = species ~ bill_length_mm + bill_depth_mm),
models = list(tree = spec_tree, forest = spec_rf)
)
bounds <- boundary_workflow_set(wf_set,
data = penguins,
response = "species", resolution = 60
)
plot_boundary(bounds,
obs_data = penguins,
x_col = "bill_length_mm", y_col = "bill_depth_mm",
true_label = "species"
)

| Resource | Link | |----|----| | Getting Started | getting-started | | High-Dimensional | high-dimensional | | tidymodels | tidymodels-workflow | | tourr | tourr-workflow | | Explorapp Guide | explorapp-guide | | Custom Adapters | custom_adapters | | Reference | Function Reference |
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.