Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC: secondary axis functionality in guide_axis() #5410

Closed
wants to merge 15 commits into from

Conversation

teunbrand
Copy link
Collaborator

@teunbrand teunbrand commented Sep 7, 2023

This PR is a proof of concept for putting the functionality of secondary axes in guide_axis().

The long term goal may be to lift over responsibilities for secondary axis from the scale system to the guide system.
In this PR, guide_axis() gains the arguments breaks, labels, minor.breaks and trans that would be needed to have secondary axis functionality. This makes guide_axis() a lot more flexibile, as these arguments can be used to override what the scale passes down. Under the hood, the whole transforming values system gets captured in a new <trans> with the scales package. Some demos below.

This is just to show that it can work similarly to using sec_axis().

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

p <- ggplot(pressure, aes(temperature, pressure)) + geom_line() +
  labs(x = "Temperature (\u00b0C)")

p + guides(x.sec = guide_axis(
  title = "Temperature (\u00b0F)",
  trans = ~.x * 9/5 + 32
))

Because we capture the transformation in a <trans> object, we can also provide one directly. There is a little bit of awkwardness in this, as the forward transform() translates secondary data to primary range and inverse() goes from primary to secondary, which is opposite to the intuition of how trans works in sec_axis().

my_trans <- trans_new(
  "temperature_trans",
  transform = \(x) (x - 32) * 5/9, # Fahrenheid to Celsius
  inverse   = \(x) x * 9/5 + 32    # Celsius to Fahrenheid
)

p + guides(x.sec  = guide_axis("Temperature (\u00b0F)", trans = my_trans))

Show that one can override the default breaks and labels:

p + guides(x.sec = guide_axis(
  breaks = breaks_width(50),
  labels = \(x) paste0(x, "\u00b0C"))
)

This PR also makes it possible to have secondary axes for discrete scales with custom labels.

ggplot(mpg, aes(drv, displ)) +
  geom_boxplot() +
  guides(x.sec = guide_axis(labels = c("Foo", "Bar", "Baz")))

Created on 2023-09-07 with reprex v2.0.2

Currently the minor breaks aren't implemented yet because #5287 provides some extra infrastructure for this.

@teunbrand teunbrand marked this pull request as draft September 7, 2023 13:48
@teunbrand
Copy link
Collaborator Author

This still needs some more thought around scales that already have non-identity transformations.

@teunbrand
Copy link
Collaborator Author

Now works better with transformed scales:

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2
library(patchwork)

p <- ggplot(pressure, aes(temperature, pressure)) + geom_line() +
  labs(x = "Temperature (\u00b0C)")

p1 <- p + scale_y_log10(sec.axis = sec_axis(sqrt))
p2 <- p + scale_y_log10() + guides(y.sec = guide_axis(trans = sqrt))
p1 | p2

Though it isn't identical w.r.t labels yet.

p1 <- p + scale_y_continuous(sec.axis = sec_axis(log10))
p2 <- p + guides(y.sec = guide_axis(trans = log10))
p1 | p2
#> Warning in self$trans(range): NaNs produced
#> Warning in fun(origin_seq): NaNs produced

Created on 2023-09-22 with reprex v2.0.2

@teunbrand teunbrand mentioned this pull request Oct 4, 2023
@teunbrand teunbrand mentioned this pull request Oct 11, 2023
@teunbrand teunbrand marked this pull request as ready for review October 24, 2023 08:55
@teunbrand
Copy link
Collaborator Author

Closing this in favour of #5620

@teunbrand teunbrand closed this Jun 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant