Skip to content

docs: randomForest finishing work — design spec + implementation plans (PR #87 & #88)#87

Merged
ehrlinger merged 3 commits into
mainfrom
docs/rf-finishing-work-design
May 21, 2026
Merged

docs: randomForest finishing work — design spec + implementation plans (PR #87 & #88)#87
ehrlinger merged 3 commits into
mainfrom
docs/rf-finishing-work-design

Conversation

@ehrlinger
Copy link
Copy Markdown
Owner

Summary

No code changes in this PR — docs/plans only.

🤖 Generated with Claude Code

ehrlinger and others added 2 commits May 21, 2026 10:32
Covers two v2.8.0 completion PRs:
- PR #87: gg_variable.randomForest classification yhat fix + stale #81/#82 close
- PR #88: multi-class gg_roc with per_class=TRUE (issue #72, no CIs)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.39%. Comparing base (4c64eed) to head (3e2eb0b).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main      #87   +/-   ##
=======================================
  Coverage   86.39%   86.39%           
=======================================
  Files          38       38           
  Lines        3021     3021           
=======================================
  Hits         2610     2610           
  Misses        411      411           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a design spec and two implementation plans for upcoming v2.8.0 “randomForest engine finishing work” (PRs #87 and #88), focusing on gg_variable.randomForest classification output shape and multi-class ROC support in gg_roc.

Changes:

  • Add a cross-PR design spec describing intended behavior, tests, and files touched for #87 and #88.
  • Add a step-by-step (TDD-oriented) implementation plan for PR #87 (gg_variable.randomForest classification + plot smooth fixes).
  • Add a step-by-step (TDD-oriented) implementation plan for PR #88 (multi-class gg_roc via per_class=TRUE + plotting/summary updates).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
dev/plans/2026-05-21-rf-finishing-work-design.md Design spec spanning PR #87/#88, including proposed API changes, behavior, and tests.
dev/plans/2026-05-21-rf-87-gg-variable-classification-plan.md Implementation plan for gg_variable.randomForest classification fix + plot.gg_variable smooth fixes.
dev/plans/2026-05-21-rf-88-multiclass-roc-plan.md Implementation plan for gg_roc(per_class=TRUE) multi-class OvR curves + plot/summary changes.
Comments suppressed due to low confidence (1)

dev/plans/2026-05-21-rf-finishing-work-design.md:194

  • In the PR #88 per_class section, the spec says the long-format data frame has columns fpr/tpr, but the package’s ROC data contract is sens/spec/pct (see R/calc_roc.R return docs and tests/testthat/test_gg_roc.R). Recommend specifying that per-class output retains sens/spec/pct (plus class), and that fpr = 1 - spec / tpr = sens are computed in the plot method if desired.
- For forests with > 2 classes: compute one-vs-rest ROC for every class *k*
  (scores = `votes[, k]`, positive = `(y == k)`), stack into a long data frame
  with columns `class` (factor), `fpr`, `tpr`.
- `attr(gg, "auc")` becomes a named numeric vector: one entry per class,
  ordered by descending AUC. Class factor levels follow the same order.
- For binary forests: `per_class = TRUE` is a no-op — returns the single-curve
  result with no `class` column and a scalar `auc` attribute (same as
  `per_class = FALSE`).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

**New signature:**

```r
gg_roc(object, which_outcome = "all", per_class = FALSE, ...)
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 3e2eb0b (plan/design doc corrections) and d511d33 (implementation test tightened). Please re-review.

Comment on lines +199 to +201
**Internal helper `calc_roc_one_vs_rest(scores, y, k)`** — single class OvR
ROC, returns a data frame `(fpr, tpr)` plus scalar AUC. Extracted so it can be
reused for both per-class computation and macro-average.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 3e2eb0b (plan/design doc corrections) and d511d33 (implementation test tightened). Please re-review.

gg_roc.rfsrc <- function(object, which_outcome, oob = TRUE, per_class = FALSE, ...) {
```

Note: the rfsrc per_class path is out of scope for this PR (tracked under issue #72). The argument is added only so `gg_roc(rfsrc_obj, per_class = TRUE)` does not error with "unused argument". Leave the body unchanged.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 3e2eb0b (plan/design doc corrections) and d511d33 (implementation test tightened). Please re-review.

rf <- randomForest::randomForest(Species ~ ., data = iris, ntree = 100L)
gg <- gg_roc(rf, per_class = TRUE)
expect_true("class" %in% names(gg))
expect_true(all(c("sens", "spec") %in% names(gg)))
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 3e2eb0b (plan/design doc corrections) and d511d33 (implementation test tightened). Please re-review.

Comment on lines +157 to +164
# For classification forests use per-class OOB vote fractions (object$votes),
# stored as yhat.<classname> columns — the same shape gg_variable.rfsrc
# produces. For regression a single numeric yhat column suffices.
if (object$type == "classification") {
preds <- object$votes # n × n_classes matrix of OOB vote fractions
colnames(preds) <- paste0("yhat.", colnames(preds))
gg_dta <- cbind(gg_dta, preds)
gg_dta$yvar <- response
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 3e2eb0b (plan/design doc corrections) and d511d33 (implementation test tightened). Please re-review.

rf <- randomForest::randomForest(Species ~ ., data = iris, ntree = 50L)
gg <- gg_variable(rf)
p <- plot(gg)
expect_true(inherits(p, "patchwork") || inherits(p, "ggplot"))
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 3e2eb0b (plan/design doc corrections) and d511d33 (implementation test tightened). Please re-review.

- design doc: add oob=TRUE to gg_roc new signature (was omitted)
- design doc: replace proposed calc_roc_one_vs_rest() with existing
  .rf_prob_matrix/.rf_one_class_roc/.rf_macro_average_roc helpers;
  document that output uses sens/spec/pct (package contract), not fpr/tpr
- plan #87: add norm.votes=FALSE row-normalization to votes extraction step
- plan #87: tighten patchwork test expectation (iris 4-predictor default
  must return patchwork, not patchwork||ggplot, to catch list regressions)
- plan #88: add pct to per_class column assertions (both occurrences)
- plan #88: correct rfsrc per_class rationale (argument is for API
  discoverability, not to prevent "unused argument" error — rfsrc uses ...)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ehrlinger added a commit that referenced this pull request May 21, 2026
…t review)

Plan #87 was corrected (via PR #87 Copilot review) to assert patchwork
specifically for the 4-predictor iris default-plot case, rather than the
loose patchwork||ggplot form that wouldn't catch a regression to a bare
list (issue #80).  Align the implementation test to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ehrlinger ehrlinger merged commit 7e4197c into main May 21, 2026
15 checks passed
ehrlinger added a commit that referenced this pull request May 21, 2026
ehrlinger added a commit that referenced this pull request May 21, 2026
…tion (PR #87)

Tests verify that gg_variable.randomForest classification forests produce:
- Per-class vote fraction columns (yhat.setosa, yhat.versicolor, yhat.virginica)
- No bare yhat column for multi-class prediction
- Valid vote fractions (0-1) that row-sum to 1
- Plottable output for multi-xvar case
- Layer_data access on single-xvar plots

All three tests currently FAIL, as expected (TDD red phase).
Implementation fix comes in T2.
ehrlinger added a commit that referenced this pull request May 21, 2026
#87)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ehrlinger added a commit that referenced this pull request May 21, 2026
…t review)

Plan #87 was corrected (via PR #87 Copilot review) to assert patchwork
specifically for the 4-predictor iris default-plot case, rather than the
loose patchwork||ggplot form that wouldn't catch a regression to a bare
list (issue #80).  Align the implementation test to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ehrlinger added a commit that referenced this pull request May 21, 2026
…h bugs (#87) (#88)

* chore: open v2.7.3.9005 dev increment (PR #87)

* test: add three failing tests for gg_variable.randomForest classification (PR #87)

Tests verify that gg_variable.randomForest classification forests produce:
- Per-class vote fraction columns (yhat.setosa, yhat.versicolor, yhat.virginica)
- No bare yhat column for multi-class prediction
- Valid vote fractions (0-1) that row-sum to 1
- Plottable output for multi-xvar case
- Layer_data access on single-xvar plots

All three tests currently FAIL, as expected (TDD red phase).
Implementation fix comes in T2.

* fix: gg_variable.randomForest classification uses object\$votes for yhat.* columns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: normalise object\$votes rows to defend against norm.votes=FALSE; update stale oob comment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: add failing tests for plot.gg_variable smooth bugs (PR #87)

* fix: plot.gg_variable binary smooth aes + add multi-class smooth block (#87)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: add vdiffr snapshots for gg_variable RF classification (PR #87)

* docs: update NEWS for PR #87 — gg_variable RF classification fix

* fix: plot.gg_variable multi-class facets use class names not integer indices

Strip the yhat. prefix from column names when building the outcome column
in the multi-class pivot loop (line ~169), so facet labels show "setosa"/
"versicolor"/"virginica" instead of 1/2/3. Add a regression test that
verifies p@data$outcome contains class names after plotting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tighten patchwork assertion to match corrected plan (#87 Copilot review)

Plan #87 was corrected (via PR #87 Copilot review) to assert patchwork
specifically for the 4-predictor iris default-plot case, rather than the
loose patchwork||ggplot form that wouldn't catch a regression to a bare
list (issue #80).  Align the implementation test to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: address Copilot review on PR #88 — oob warning + factor level order

- gg_variable.randomForest: replace silent no-op oob override with an
  explicit warning when oob=FALSE is supplied, since in-bag class
  probabilities are not available via the randomForest API.
- plot.gg_variable: set outcome factor levels from gg_dta_y column order
  rather than factor() default (alphabetical), so multi-class facet panels
  follow the model's class ordering regardless of locale.
- Add two new tests: oob=FALSE warning, and outcome factor level order.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Meta: gg_roc enhancements (multi-class + confidence intervals)

2 participants