Skip to content

Commit 4f9dc48

Browse files
committed
docs/test: smooth=TRUE is intentionally a no-op for factor predictors in plot.gg_variable
geom_smooth requires a continuous x-axis; for factor predictors the boxplot IQR already serves as the spread summary. Add inline comments to all three factor-predictor branches (binary classification, multi-class classification, regression) and three regression-test guard tests to lock in the no-op behaviour.
1 parent ae0b18e commit 4f9dc48

2 files changed

Lines changed: 68 additions & 2 deletions

File tree

R/plot.gg_variable.R

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,11 @@ plot.gg_variable <- function(x, # nolint: cyclocomp_linter
526526
)
527527
}
528528
} else {
529-
# Factor predictor: jitter + boxplot coloured by observed class
529+
# Factor predictor: jitter + boxplot coloured by observed class.
530+
# smooth=TRUE is intentionally a no-op here: geom_smooth requires
531+
# a continuous x-axis and has no meaningful interpretation for
532+
# discrete factor levels. The boxplot IQR serves as the spread
533+
# summary.
530534
gg_plt[[ind]] <- gg_plt[[ind]] +
531535
ggplot2::geom_jitter(
532536
ggplot2::aes(
@@ -565,6 +569,10 @@ plot.gg_variable <- function(x, # nolint: cyclocomp_linter
565569
)
566570
}
567571
} else {
572+
# Factor predictor (multi-class): boxplot + jitter per facet.
573+
# smooth=TRUE is intentionally a no-op here for the same reason
574+
# as the binary factor path above — geom_smooth requires a
575+
# continuous x-axis.
568576
gg_plt[[ind]] <- gg_plt[[ind]] +
569577
ggplot2::geom_boxplot(
570578
ggplot2::aes(x = .data$var, y = .data$yhat),
@@ -605,7 +613,10 @@ plot.gg_variable <- function(x, # nolint: cyclocomp_linter
605613
ggplot2::geom_smooth(ggplot2::aes(x = .data$var, y = .data$yhat), ...)
606614
}
607615
} else {
608-
# Factor predictor: boxplot + jitter
616+
# Factor predictor (regression): boxplot + jitter.
617+
# smooth=TRUE is intentionally a no-op here: geom_smooth requires a
618+
# continuous x-axis and has no meaningful interpretation for discrete
619+
# factor levels. The boxplot IQR serves as the spread summary.
609620
gg_plt[[ind]] <- gg_plt[[ind]] +
610621
ggplot2::geom_boxplot(
611622
ggplot2::aes(x = .data$var, y = .data$yhat),

tests/testthat/test_gg_variable.R

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,3 +492,58 @@ test_that("gg_variable.randomForest: oob=FALSE triggers a warning", {
492492
expect_s3_class(gg, "gg_variable")
493493
expect_true("yhat.setosa" %in% names(gg))
494494
})
495+
496+
## ── smooth=TRUE is a no-op for factor predictors (all families) ──────────────
497+
498+
test_that("plot.gg_variable binary classification + factor predictor: smooth=TRUE is no-op (no error, 2 layers)", {
499+
skip_if_not_installed("randomForest")
500+
set.seed(42L)
501+
bin_data <- iris[iris$Species != "virginica", ]
502+
bin_data$Species <- droplevels(bin_data$Species)
503+
bin_data$size <- cut(bin_data$Petal.Length, 2L, labels = c("small", "large"))
504+
rf <- randomForest::randomForest(Species ~ size + Sepal.Width, data = bin_data,
505+
ntree = 50L)
506+
gg <- gg_variable(rf)
507+
# smooth=TRUE with a factor predictor must not error
508+
expect_no_error({
509+
p <- plot(gg, xvar = "size", smooth = TRUE)
510+
})
511+
p <- plot(gg, xvar = "size", smooth = TRUE)
512+
expect_s3_class(p, "ggplot")
513+
# Boxplot + jitter — no smooth layer added
514+
expect_equal(length(p$layers), 2L)
515+
})
516+
517+
test_that("plot.gg_variable multi-class classification + factor predictor: smooth=TRUE is no-op (no error)", {
518+
skip_if_not_installed("randomForest")
519+
set.seed(42L)
520+
iris2 <- iris
521+
iris2$size <- cut(iris2$Petal.Length, 3L, labels = c("small", "medium", "large"))
522+
rf <- randomForest::randomForest(Species ~ size + Sepal.Width, data = iris2,
523+
ntree = 50L)
524+
gg <- gg_variable(rf)
525+
# smooth=TRUE with a factor predictor must not error
526+
expect_no_error({
527+
p <- plot(gg, xvar = "size", smooth = TRUE)
528+
})
529+
p <- plot(gg, xvar = "size", smooth = TRUE)
530+
expect_s3_class(p, "ggplot")
531+
})
532+
533+
test_that("plot.gg_variable regression + factor predictor: smooth=TRUE is no-op (no error, 2 layers)", {
534+
skip_if_not_installed("randomForest")
535+
set.seed(42L)
536+
iris2 <- iris
537+
iris2$size <- cut(iris2$Petal.Length, 3L, labels = c("small", "medium", "large"))
538+
rf <- randomForest::randomForest(Sepal.Length ~ size + Sepal.Width, data = iris2,
539+
ntree = 50L)
540+
gg <- gg_variable(rf)
541+
# smooth=TRUE with a factor predictor must not error
542+
expect_no_error({
543+
p <- plot(gg, xvar = "size", smooth = TRUE)
544+
})
545+
p <- plot(gg, xvar = "size", smooth = TRUE)
546+
expect_s3_class(p, "ggplot")
547+
# Boxplot + jitter — no smooth layer added
548+
expect_equal(length(p$layers), 2L)
549+
})

0 commit comments

Comments
 (0)