Skip to content

Commit efd7f0d

Browse files
authored
Fix stat_function() for transformed scales (#3908)
* Attempt to fix stat_function(). Doesn't work yet. * fix stat_function to work with and without explicit y mapping
1 parent 7f11303 commit efd7f0d

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
* Default continuous color scales (i.e., the `options()` `ggplot2.continuous.colour` and `ggplot2.continuous.fill`, which inform the `type` argument of `scale_fill_continuous()` and `scale_colour_continuous()`) now accept a function, which allows more control over these default `continuous_scale()`s (@cpsievert, #3827)
1010

11+
* `stat_function()` now works with transformed y axes, e.g. `scale_y_log10()`
12+
(@clauswilke, #3905).
13+
1114
* A newly added geom `geom_density_2d_filled()` and associated stat
1215
`stat_density_2d_filled()` can draw filled density contours
1316
(@clauswilke, #3846).

R/stat-function.r

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ stat_function <- function(mapping = NULL, data = NULL,
9797
#' @usage NULL
9898
#' @export
9999
StatFunction <- ggproto("StatFunction", Stat,
100-
default_aes = aes(y = after_stat(y)),
100+
default_aes = aes(y = after_scale(y)),
101101

102102
compute_group = function(data, scales, fun, xlim = NULL, n = 101, args = list()) {
103103
range <- xlim %||% scales$x$dimension()
@@ -113,9 +113,15 @@ StatFunction <- ggproto("StatFunction", Stat,
113113

114114
if (is.formula(fun)) fun <- as_function(fun)
115115

116+
y_out <- do.call(fun, c(list(quote(x_trans)), args))
117+
if (!is.null(scales$y) && !scales$y$is_discrete()) {
118+
# For continuous scales, need to apply transform
119+
y_out <- scales$y$trans$transform(y_out)
120+
}
121+
116122
new_data_frame(list(
117123
x = xseq,
118-
y = do.call(fun, c(list(quote(x_trans)), args))
124+
y = y_out
119125
))
120126
}
121127
)

tests/testthat/test-stats-function.r

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,51 @@ test_that("works with discrete x", {
3535
expect_equal(ret$y, 1:2)
3636
})
3737

38+
test_that("works with transformed scales", {
39+
dat <- data_frame(x = 1:10, y = (1:10)^2)
40+
41+
# first without explicit mapping of y
42+
base <- ggplot(dat, aes(x, group = 1)) +
43+
stat_function(fun = ~ .x^2, n = 5)
44+
45+
ret <- layer_data(base)
46+
expect_equal(nrow(ret), 5)
47+
expect_equal(ret$y, ret$x^2)
48+
49+
ret <- layer_data(base + scale_x_log10())
50+
expect_equal(nrow(ret), 5)
51+
expect_equal(ret$y, (10^ret$x)^2)
52+
53+
ret <- layer_data(base + scale_y_log10())
54+
expect_equal(nrow(ret), 5)
55+
expect_equal(10^ret$y, ret$x^2)
56+
57+
ret <- layer_data(base + scale_x_log10() + scale_y_log10())
58+
expect_equal(nrow(ret), 5)
59+
expect_equal(10^ret$y, (10^ret$x)^2)
60+
61+
# now with explicit mapping of y
62+
base <- ggplot(dat, aes(x, y)) + geom_point() +
63+
stat_function(fun = ~ .x^2, n = 5)
64+
65+
ret <- layer_data(base, 2)
66+
expect_equal(nrow(ret), 5)
67+
expect_equal(ret$y, ret$x^2)
68+
69+
ret <- layer_data(base + scale_x_log10(), 2)
70+
expect_equal(nrow(ret), 5)
71+
expect_equal(ret$y, (10^ret$x)^2)
72+
73+
ret <- layer_data(base + scale_y_log10(), 2)
74+
expect_equal(nrow(ret), 5)
75+
expect_equal(10^ret$y, ret$x^2)
76+
77+
ret <- layer_data(base + scale_x_log10() + scale_y_log10(), 2)
78+
expect_equal(nrow(ret), 5)
79+
expect_equal(10^ret$y, (10^ret$x)^2)
80+
})
81+
82+
3883
test_that("works with formula syntax", {
3984
dat <- data_frame(x = 1:10)
4085

0 commit comments

Comments
 (0)