diff --git a/R/scale-.R b/R/scale-.R index 81bef1d5cc..d644bc036b 100644 --- a/R/scale-.R +++ b/R/scale-.R @@ -648,7 +648,7 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, domain <- suppressWarnings(self$trans$transform(self$trans$domain)) domain <- sort(domain) # To avoid NaN causing issues. NaN are dropped by the sort() - if (length(domain) == 2) { + if (length(domain) == 2 && !zero_range(domain)) { limits <- oob_squish(limits, domain) } diff --git a/tests/testthat/_snaps/scales.md b/tests/testthat/_snaps/scales.md index 8fcbd21745..b9adefae05 100644 --- a/tests/testthat/_snaps/scales.md +++ b/tests/testthat/_snaps/scales.md @@ -42,3 +42,10 @@ `breaks` and `labels` are different lengths +# numeric scale transforms can produce breaks + + Code + test_breaks("log", limits = c(0.1, 1000)) + Output + [1] NA 1.00000 20.08554 403.42879 + diff --git a/tests/testthat/test-scales.R b/tests/testthat/test-scales.R index ecf9da336a..ea6318a5a1 100644 --- a/tests/testthat/test-scales.R +++ b/tests/testthat/test-scales.R @@ -468,3 +468,67 @@ test_that("staged aesthetics are backtransformed properly (#4155)", { # x / 2 should be 16 / 2 = 8, thus the result should be sqrt(8) on scale_x_sqrt() expect_equal(layer_data(p)$x, sqrt(8)) }) + +test_that("numeric scale transforms can produce breaks", { + + test_breaks <- function(trans, limits) { + scale <- scale_x_continuous(trans = trans) + scale$train(scale$transform(limits)) + view <- view_scale_primary(scale) + scale$trans$inverse(view$get_breaks()) + } + + expect_equal(test_breaks("asn", limits = c(0, 1)), + seq(0, 1, by = 0.25)) + + expect_equal(test_breaks("sqrt", limits = c(0, 10)), + seq(0, 10, by = 2.5)) + + expect_equal(test_breaks("atanh", limits = c(-0.9, 0.9)), + c(NA, -0.5, 0, 0.5, NA)) + + # Broken, should fix on {scale}'s side + # expect_equal(test_breaks(boxcox_trans(0), limits = c(0, 10)), ...) + + expect_equal(test_breaks(modulus_trans(0), c(-10, 10)), + seq(-10, 10, by = 5)) + + expect_equal(test_breaks(yj_trans(0), c(-10, 10)), + seq(-10, 10, by = 5)) + + expect_equal(test_breaks("exp", c(-10, 10)), + seq(-10, 10, by = 5)) + + expect_equal(test_breaks("identity", limits = c(-10, 10)), + seq(-10, 10, by = 5)) + + # irrational numbers, so snapshot values + expect_snapshot(test_breaks("log", limits = c(0.1, 1000))) + + expect_equal(test_breaks("log10", limits = c(0.1, 1000)), + 10 ^ seq(-1, 3)) + + expect_equal(test_breaks("log2", limits = c(0.5, 32)), + c(0.5, 2, 8, 32)) + + expect_equal(test_breaks("log1p", limits = c(0, 10)), + seq(0, 10, by = 2.5)) + + expect_equal(test_breaks("pseudo_log", limits = c(-10, 10)), + seq(-10, 10, by = 5)) + + expect_equal(test_breaks("logit", limits = c(0.001, 0.999)), + c(NA, 0.25, 0.5, 0.75, NA)) + + expect_equal(test_breaks("probit", limits = c(0.001, 0.999)), + c(NA, 0.25, 0.5, 0.75, NA)) + + expect_equal(test_breaks("reciprocal", limits = c(1, 10)), + c(NA, 2.5, 5, 7.5, 10)) + + expect_equal(test_breaks("reverse", limits = c(-10, 10)), + seq(-10, 10, by = 5)) + + expect_equal(test_breaks("sqrt", limits = c(0, 10)), + seq(0, 10, by = 2.5)) +})