Skip to content

Commit 475042e

Browse files
Convert formula to function in sec_axis() (#3038)
1 parent 5d9cb8b commit 475042e

File tree

3 files changed

+22
-22
lines changed

3 files changed

+22
-22
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ core developer team.
119119
* `stat_bin()` now handles data with only one unique value (@yutannihilation
120120
#3047).
121121

122+
* `sec_axis()` now accepts functions as well as formulas (@yutannihilation, #3031).
123+
122124
# ggplot2 3.1.0
123125

124126
## Breaking changes

R/axis-secondary.R

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#' secondary axis, positioned opposite of the primary axis. All secondary
55
#' axes must be based on a one-to-one transformation of the primary axes.
66
#'
7-
#' @param trans A transformation formula
7+
#' @param trans A formula or function of transformation
88
#'
99
#' @param name The name of the secondary axis
1010
#'
@@ -33,8 +33,8 @@
3333
#' Unlike other continuous scales, secondary axis transformations for date and datetime scales
3434
#' must respect their primary POSIX data structure.
3535
#' This means they may only be transformed via addition or subtraction, e.g.
36-
#' `~. + hms::hms(days = 8)`, or
37-
#' `~.- 8*60*60`. Nonlinear transformations will return an error.
36+
#' `~ . + hms::hms(days = 8)`, or
37+
#' `~ . - 8*60*60`. Nonlinear transformations will return an error.
3838
#' To produce a time-since-event secondary axis in this context, users
3939
#' may consider adapting secondary axis labels.
4040
#'
@@ -43,16 +43,16 @@
4343
#' geom_point()
4444
#'
4545
#' # Create a simple secondary axis
46-
#' p + scale_y_continuous(sec.axis = sec_axis(~.+10))
46+
#' p + scale_y_continuous(sec.axis = sec_axis(~ . + 10))
4747
#'
4848
#' # Inherit the name from the primary axis
49-
#' p + scale_y_continuous("Miles/gallon", sec.axis = sec_axis(~.+10, name = derive()))
49+
#' p + scale_y_continuous("Miles/gallon", sec.axis = sec_axis(~ . + 10, name = derive()))
5050
#'
5151
#' # Duplicate the primary axis
5252
#' p + scale_y_continuous(sec.axis = dup_axis())
5353
#'
5454
#' # You can pass in a formula as a shorthand
55-
#' p + scale_y_continuous(sec.axis = ~.^2)
55+
#' p + scale_y_continuous(sec.axis = ~ .^2)
5656
#'
5757
#' # Secondary axes work for date and datetime scales too:
5858
#' df <- data.frame(
@@ -75,12 +75,15 @@
7575
#' # or to transform axes for different timezones
7676
#' ggplot(df, aes(x = dx, y = price)) + geom_line() +
7777
#' scale_x_datetime("GMT", date_labels = "%b %d %I %p",
78-
#' sec.axis = sec_axis(~. + 8*3600, name = "GMT+8",
78+
#' sec.axis = sec_axis(~ . + 8 * 3600, name = "GMT+8",
7979
#' labels = scales::time_format("%b %d %I %p")))
8080
#'
8181
#' @export
8282
sec_axis <- function(trans = NULL, name = waiver(), breaks = waiver(), labels = waiver()) {
83-
if (!is.formula(trans)) stop("transformation for secondary axes must be a formula", call. = FALSE)
83+
# sec_axis() historically accpeted two-sided formula, so be permissive.
84+
if (length(trans) > 2) trans <- trans[c(1,3)]
85+
86+
trans <- rlang::as_function(trans)
8487
ggproto(NULL, AxisSecondary,
8588
trans = trans,
8689
name = name,
@@ -142,20 +145,15 @@ AxisSecondary <- ggproto("AxisSecondary", NULL,
142145
# Inherit settings from the primary axis/scale
143146
init = function(self, scale) {
144147
if (self$empty()) return()
145-
if (!is.formula(self$trans)) stop("transformation for secondary axes must be a formula", call. = FALSE)
148+
if (!is.function(self$trans)) stop("transformation for secondary axes must be a function", call. = FALSE)
146149
if (is.derived(self$name) && !is.waive(scale$name)) self$name <- scale$name
147150
if (is.derived(self$breaks)) self$breaks <- scale$breaks
148151
if (is.waive(self$breaks)) self$breaks <- scale$trans$breaks
149152
if (is.derived(self$labels)) self$labels <- scale$labels
150153
},
151154

152155
transform_range = function(self, range) {
153-
range <- new_data_frame(list(. = range))
154-
rlang::eval_tidy(
155-
rlang::f_rhs(self$trans),
156-
data = range,
157-
env = rlang::f_env(self$trans)
158-
)
156+
self$trans(range)
159157
},
160158

161159
mono_test = function(self, scale){

man/sec_axis.Rd

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)