11  Plotting model objects

library(rtemis.draw)

Attaching package: 'rtemis.draw'
The following object is masked from 'package:graphics':

    Axis

Use draw_*() when you supply plotting data. Use plot() or a plot_*() generic when you already have a fitted object. The methods in this chapter extract predictions, metrics, or training records from rtemis S7 objects and render them with rtemis.draw.

These examples additionally require rtemis; the learning-curve example uses the dataset package MASS. The rtemis:: prefix selects the model methods. rtemis registers the plot() methods for MassGLM and SupervisedSession; rtemis.draw supplies their renderers.

11.1 Regression predictions

Fit a linear model for fuel economy using vehicle weight and horsepower. The last column is the outcome in rtemis::train(). Reserve eight cars for testing and use serial execution for this small example:

set.seed(48)
training_rows <- sample(seq_len(nrow(mtcars)), 24)
cars <- mtcars[c("wt", "hp", "mpg")]
regression <- rtemis::train(
  cars[training_rows, ], dat_test = cars[-training_rows, ],
  hyperparameters = rtemis::setup_GLM(),
  execution_config = rtemis::setup_SerialExecution(), verbosity = 0L
)

plot_true_pred() draws the available samples. Here we show the predictions against the identity line, without adding a fitted trend:

prediction_chart <- rtemis::plot_true_pred(
  regression, fit = NULL, rsq = FALSE,
  xlab = "Observed fuel economy (mpg)", ylab = "Predicted fuel economy (mpg)",
  title = "Fuel economy predictions"
)
prediction_chart

Points near the diagonal have accurate predictions. Training and test samples have separate colors. Use what = "test" to focus on held-out predictions; what = "all" includes every available sample.

11.2 Classification predictions

For a classifier, the same plot_true_pred() generic returns a confusion matrix. Fit an iris classification tree using only sepal measurements, with 15 flowers per species reserved for testing:

set.seed(42)
flower_rows <- unlist(lapply(
  split(seq_len(nrow(iris)), iris[["Species"]]), sample, size = 35
))
flowers <- iris[c("Sepal.Length", "Sepal.Width", "Species")]
classifier <- rtemis::train(
  flowers[flower_rows, ], dat_test = flowers[-flower_rows, ],
  hyperparameters = rtemis::setup_CART(cp = 0.03, minbucket = 5L),
  execution_config = rtemis::setup_SerialExecution(), verbosity = 0L
)
confusion_chart <- rtemis::plot_true_pred(
  classifier, what = "test", show_metrics = FALSE, font_size = 11
)
confusion_chart

Rows are reference species and columns are predicted species. The off-diagonal counts show which species the model confuses. Omit show_metrics = FALSE to include the surrounding metric summaries. Request what = "all" for a figure containing all available sample matrices.

11.2.1 ROC curves from stored probabilities

plot_roc() uses the classifier’s stored probabilities. Select the same test sample to examine one-versus-rest discrimination:

roc_chart <- rtemis::plot_roc(classifier, what = "test")
roc_chart

Each curve compares one species with the other two. See Classification diagnostics for the interpretation of AUC and confusion metrics, and for plots made directly from predictions.

11.3 Learning curves

Learning curves require a learner that records losses during fitting. This example fits a LINAD model to MASS::mcycle, measurements of acceleration through time in a simulated motorcycle accident:

learning_model <- rtemis::train(
  MASS::mcycle,
  hyperparameters = rtemis::setup_LINAD(max_leaves = 8L),
  execution_config = rtemis::setup_SerialExecution(), verbosity = 0L
)
learning_chart <- rtemis::plot_learning(learning_model)
learning_chart

The horizontal axis counts tree leaves, and the vertical axis shows the recorded training loss. This example has no validation sample: decreasing training loss alone does not establish better performance on new data. Other supported learners may record epochs or iterations and include a validation curve.

11.4 Metrics across resamples

For resampled models, plot_metric() shows the stored score from each fold. Fit five-fold cross-validation on the fuel-economy data and compare training and test RMSE:

resampled <- rtemis::train(
  cars, hyperparameters = rtemis::setup_GLM(),
  outer_resampling_config = rtemis::setup_KFold(n_resamples = 5L, seed = 31L),
  execution_config = rtemis::setup_SerialExecution(), verbosity = 0L
)
metric_chart <- rtemis::plot_metric(
  resampled, metric = "rmse", ylab = "RMSE (mpg)",
  title = "Fuel economy error across five folds"
)
metric_chart

Each point is one fold’s score. The boxes describe the spread of those scores, not a confidence interval for generalization error. Resampled plot_true_pred() combines prediction rows across folds; if observations appear in several folds, their repeated predictions remain in that view. For importance stored across fits, see Variable importance. For pooled confusion counts, classification metrics, and pooled versus per-fold ROC curves, continue with Resampled classifiers.

11.5 Execution timelines

plot_session() shows the steps recorded during a model’s execution. The resampled fit provides a timeline of the five-fold run:

session_chart <- rtemis::plot_session(resampled,
                                         title = "Five-fold execution",
                                         height = 850)
session_chart

Bar positions and lengths show elapsed time, and colors identify step kinds. Hover a bar for its recorded details. Durations vary between runs and machines. plot(resampled@session) opens the same view directly from the session object. On narrow displays, the legend moves below the timeline and the time axis uses fewer ticks. Increase height when there are many steps.

11.6 Mass-univariate models

A MassGLM result contains one fitted model per outcome. This example relates vehicle weight to six other measurements. Standardizing the outcomes makes their coefficients comparable in outcome standard deviations per 1,000 lb of vehicle weight:

mass_model <- rtemis::massGLM(
  mtcars["wt"], mtcars[c("mpg", "hp", "disp", "qsec", "drat", "carb")],
  scale_y = TRUE, center_y = TRUE, verbosity = 0L
)
2026-10-02 10:33:00 Done in 0.03 seconds. [rtemis::massGLM]

With rtemis.draw loaded, plot() returns a volcano plot. Select the weight coefficient explicitly:

mass_volcano <- plot(mass_model, coefname = "wt",
                     xlab = "Standardized outcome change per 1,000 lb",
                     title = "Associations with vehicle weight")
mass_volcano

The categorical Manhattan view retains the outcome order:

mass_manhattan <- rtemis::plot_manhattan(
  mass_model, coefname = "wt", title = "Weight associations by outcome"
)
mass_manhattan

Both views use the significance plotting contract: raw p-values are adjusted across all six outcomes, using Holm’s method by default. These are exploratory associations, without adjustment for other vehicle characteristics.

11.7 Compare models with present()

present() selects a view for one fitted model or compares a list of models. Fit a regression tree on the same training and test rows as the linear model:

regression_tree <- rtemis::train(
  cars[training_rows, ], dat_test = cars[-training_rows, ],
  hyperparameters = rtemis::setup_CART(cp = 0.03, minbucket = 3L),
  execution_config = rtemis::setup_SerialExecution(), verbosity = 0L
)
comparison_chart <- rtemis::present(
  list(Linear = regression, Tree = regression_tree),
  metric = "rmse", verbosity = 0L
)
comparison_chart

Lower RMSE is better. Compare models on the same observations; this tiny held-out sample illustrates the API rather than providing a definitive algorithm comparison. verbosity = 0L omits the accompanying text description. For a single model, present() selects prediction, ROC, or resampled-metric plots according to the object type.

11.8 Compose and export a figure

draw_panels() combines existing ECharts drawings into one figure. This layout places the fuel-economy predictions above the cross-validation error summary, leaving room for labels on a narrow page:

diagnostics_figure <- draw_panels(
  list(prediction_chart, metric_chart), ncol = 1, gap = 24,
  width = "100%", height = 950
)
diagnostics_figure

Each panel retains its own controls. Set ncol = 2 for a side-by-side layout when your output is wide enough. Save the complete figure with one call:

save_drawing(diagnostics_figure, "model-diagnostics.svg", width = 850, height = 950)

See Export for output options.

© 2026 E.D. Gennatas