Skip to content

Commit 26ac887

Browse files
ehrlingerclaude
andcommitted
Fold v2.7.1 follow-ups: news source consolidation + vimp legend merge
* ggrandomforests.news() now reads NEWS.md (the canonical change log R also exposes via utils::news()). Removes inst/NEWS, which had silently drifted to v2.4.0 across three releases -- users running the helper were seeing year-old version info. Adds a fallback to inst/NEWS for legacy installs and a regression test that the bundled NEWS.md contains the installed package version. * plot.gg_vimp(): merge the duplicate legend. Previously fill and color were both mapped to `positive` but only the fill legend got a custom title via labs(), leaving a second redundant legend titled "positive" (the column name). Both aesthetics now share the "VIMP > 0" title by default so ggplot collapses them into a single legend. Regression test asserts p$labels$fill == p$labels$colour == "VIMP > 0". No DESCRIPTION bump -- v2.7.1 has not been tagged or submitted to CRAN yet; these fold into the same release. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b79f6fa commit 26ac887

7 files changed

Lines changed: 101 additions & 30 deletions

File tree

NEWS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ ggRandomForests v2.7.1
2626
non-empty layers for every supported forest family. Catches the
2727
empty-figure class of bug (transform/plot column-name mismatch) without
2828
requiring visual inspection.
29+
* `ggrandomforests.news()` now reads `NEWS.md` (the canonical change log
30+
R also surfaces via `utils::news()`). The legacy hand-maintained
31+
`inst/NEWS` has been removed — it had silently drifted to v2.4.0
32+
(June 2025) across three releases, so users running the helper saw
33+
stale version info. One source of truth, no more drift window.
34+
* Fix `plot.gg_vimp()` legend duplication: the bar geom mapped both
35+
`fill` and `color` to the `positive` column, but only the fill legend
36+
was titled "VIMP > 0", leaving a redundant second legend titled
37+
"positive". Both aesthetics now share the "VIMP > 0" title so ggplot
38+
merges them into a single legend by default.
2939

3040
ggRandomForests v2.7.0
3141
=====================

R/ggrandomforests.news.R

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
11
#' Display the ggRandomForests NEWS file
22
#'
3-
#' Opens the package NEWS file in the system pager so users can read the
4-
#' version history and change log without leaving their R session.
3+
#' Opens the package change log in the system pager so users can read the
4+
#' version history without leaving their R session. The function reads
5+
#' \code{NEWS.md} from the installed package root (the canonical change log
6+
#' that R also surfaces via \code{utils::news()}). \code{inst/NEWS} was
7+
#' removed in v2.7.1 to eliminate the duplicate-source-of-truth maintenance
8+
#' hole that left the legacy file frozen at v2.4.0; if any installation
9+
#' still ships an \code{inst/NEWS}, this function falls back to it.
510
#'
611
#' @param ... Currently unused; reserved for future arguments.
712
#'
813
#' @return Called for its side-effect of opening the NEWS file in the system
9-
#' pager (\code{file.show}). Returns \code{invisible(NULL)}.
14+
#' pager (\code{file.show}). Returns \code{invisible(NULL)}.
1015
#'
1116
#' @keywords internal
1217
ggrandomforests.news <- function(...) {
13-
newsfile <- file.path(system.file(package="ggRandomForests"), "NEWS")
18+
newsfile <- system.file("NEWS.md", package = "ggRandomForests")
19+
if (!nzchar(newsfile)) {
20+
# Fallback for legacy installs that still bundle inst/NEWS.
21+
newsfile <- system.file("NEWS", package = "ggRandomForests")
22+
}
23+
if (!nzchar(newsfile)) {
24+
warning("Could not locate a NEWS file for ggRandomForests.",
25+
call. = FALSE)
26+
return(invisible(NULL))
27+
}
1428
file.show(newsfile)
15-
}
29+
}

R/plot.gg_vimp.R

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ plot.gg_vimp <- function(x, relative, lbls, ...) {
8989

9090
# When there are both positive and negative VIMP values, colour the bars
9191
# differently so the user can immediately see which variables are below zero
92-
# (i.e. hurt predictive accuracy on average).
92+
# (i.e. hurt predictive accuracy on average). Both `fill` and `color` are
93+
# mapped to the same column; we give them the same legend title ("VIMP > 0")
94+
# so ggplot collapses them into a single legend rather than rendering one
95+
# legend titled "VIMP > 0" (fill) and a second titled "positive" (color).
96+
legend_title <- "VIMP > 0"
9397
if (length(unique(gg_dta$positive)) > 1) {
9498
gg_plt <- gg_plt +
9599
ggplot2::geom_bar(
@@ -112,7 +116,11 @@ plot.gg_vimp <- function(x, relative, lbls, ...) {
112116
width = .5,
113117
)
114118
}
115-
gg_plt <- gg_plt + labs(x = "", y = msr)
119+
# Set both legends' titles to the same string so ggplot merges them.
120+
# Users can override with their own labs() call after the fact.
121+
gg_plt <- gg_plt +
122+
ggplot2::labs(x = "", y = msr,
123+
fill = legend_title, color = legend_title)
116124

117125
if (!missing(lbls)) {
118126
# Map internal variable names to human-readable labels. lbls should be a

inst/NEWS

Lines changed: 0 additions & 15 deletions
This file was deleted.

man/ggrandomforests.news.Rd

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,35 @@
1-
# Tests for ggrandomforests.news
1+
# Tests for ggrandomforests.news()
2+
#
3+
# v2.7.1 consolidated the helper to read NEWS.md (the canonical change log
4+
# R also exposes via utils::news()) instead of the legacy inst/NEWS plain
5+
# text file. These tests guard against silent drift back to a separate
6+
# hand-maintained source.
27

3-
test_that("ggrandomforests.news NEWS file exists in package", {
4-
newsfile <- file.path(system.file(package = "ggRandomForests"), "NEWS")
5-
expect_true(file.exists(newsfile))
8+
test_that("NEWS.md is bundled with the installed package", {
9+
nf <- system.file("NEWS.md", package = "ggRandomForests")
10+
expect_true(nzchar(nf))
11+
expect_true(file.exists(nf))
12+
})
13+
14+
test_that("Bundled NEWS.md reflects the installed package version", {
15+
# Reading NEWS.md and finding the DESCRIPTION version in it ensures the
16+
# change-log entry was written before the version bump landed — i.e. that
17+
# users running ggrandomforests.news() see the correct release.
18+
ver <- as.character(utils::packageVersion("ggRandomForests"))
19+
nf <- system.file("NEWS.md", package = "ggRandomForests")
20+
txt <- readLines(nf, warn = FALSE)
21+
expect_true(any(grepl(ver, txt, fixed = TRUE)),
22+
info = sprintf("Installed version %s not found in %s", ver, nf))
623
})
724

825
test_that("ggrandomforests.news is callable without error", {
9-
# file.show opens the file but should not throw an error
1026
expect_error(ggrandomforests.news(), NA)
1127
})
28+
29+
test_that("inst/NEWS is no longer the source of truth", {
30+
# Defensive: if a future change re-introduces inst/NEWS, this test won't
31+
# fail (the helper still falls back to it) -- but we explicitly assert
32+
# NEWS.md takes priority when both exist.
33+
nf_md <- system.file("NEWS.md", package = "ggRandomForests")
34+
expect_true(nzchar(nf_md))
35+
})

tests/testthat/test_plot_layer_data.R

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,31 @@ test_that("plot.gg_vimp renders one bar per variable", {
287287
expect_equal(nrow(ld), length(rf$xvar.names))
288288
})
289289

290+
test_that("plot.gg_vimp produces a single merged 'VIMP > 0' legend", {
291+
# Regression: previously the bar geom mapped both `fill` and `color` to
292+
# `positive` but only the fill legend got a custom title via labs(). ggplot
293+
# rendered two legends -- one labelled "VIMP > 0" (fill) and one labelled
294+
# "positive" (color, the column name). Setting matching titles on both
295+
# aesthetics merges them into one.
296+
data(pbc, package = "randomForestSRC")
297+
pbc_min <- pbc[!is.na(pbc$treatment), ]
298+
set.seed(42)
299+
rf <- randomForestSRC::rfsrc(
300+
Surv(days, status) ~ ., data = pbc_min,
301+
ntree = 100, importance = TRUE, na.action = "na.impute"
302+
)
303+
gg <- gg_vimp(rf)
304+
# Sanity: ensure both signs of VIMP are present so the fill aesthetic is
305+
# actually in play.
306+
expect_true(length(unique(gg$positive)) > 1)
307+
308+
p <- plot(gg)
309+
expect_equal(p$labels$fill, "VIMP > 0")
310+
expect_equal(p$labels$colour, "VIMP > 0")
311+
# The two aesthetic legend titles must match for ggplot to merge them.
312+
expect_identical(p$labels$fill, p$labels$colour)
313+
})
314+
290315
# ----------------------------------------------------------------------------
291316
# gg_variable
292317
# ----------------------------------------------------------------------------

0 commit comments

Comments
 (0)