Skip to content

Allow functional limits in continuous scales #2334

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

Merged
merged 5 commits into from
Apr 24, 2019

Conversation

econandrew
Copy link
Contributor

An implementation of the idea in #2307, for consideration.

Motivation is to allow programmatic, data-agnostic control of scale limits, taking advantage of rather than having to replicate ggplot's aesthetic calculations. For example, suppose you want limits to always be a multiple of 50:

library(ggplot2)
library(dplyr)

# Example 1: stacked position adjustment

p1 <- ggplot(mpg, aes(class)) + geom_bar(aes(fill = drv))

# define a function to determine limits
limiter <- function(by) {
  function(limits) {
    low <- floor(limits[1]/by)*by
    high <- ceiling(limits[2]/by)*by
    c(low, high)
  }
}

# with PR, you can write something like...
p1 + scale_y_continuous(limits = limiter(50))

# ...current alternative would have to be
themax <- mpg %>% group_by(class) %>% summarise(count = n()) %>% pull(count) %>% max
p1 + scale_y_continuous(limits = limiter(50)(c(0, themax)))

Copy link
Member

@hadley hadley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a small change and it seems useful, so lets do it! A few suggestions in the comments.

Also needs one or two unit tests. Can you please have a look at the existing tests and think about where they should go?

R/scale-.r Outdated
# if scale contains a NULL, use the default scale range
# if scale contains a NA, use the default range for that axis, otherwise
# use the user defined limit for that axis
get_limits = function(self) {
if (self$is_empty()) return(c(0, 1))

if (!is.null(self$limits)) {
if (is.function(self$limits)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're adding another condition here, can you please reframe the if statement along these lines:

if (is.null()) {

} else if (is.function()) {

} else if (is.numeric()) {
  
} else {
  stop("Informative error message", call. = FALSE) 
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did rework this conditional to be more intuitive but since get_limits() is called by both discrete and continuous scales and can be passed character, numeric, POSIXt and now function classes, I ultimately did not add an explicit is.numeric conditional nor an error message. Happy to update further if necessary.

@dpseidel
Copy link
Collaborator

Hey @econandrew if you're still interested in this PR, I'm around (:wave: summer intern!) and can help you get this over the finish line if you'd like. Let me know if I can help in anyway.

@thomasp85
Copy link
Member

@dpseidel would you consider finishing this off?

@thomasp85 thomasp85 added this to the ggplot2 3.2.0 milestone Apr 11, 2019
@dpseidel
Copy link
Collaborator

Yep happy to.

Merge remote-tracking branch 'upstream/master' into allow-functional-limits

# Conflicts:
#	R/scale-.r
@dpseidel dpseidel requested a review from hadley April 13, 2019 21:55
@hadley
Copy link
Member

hadley commented Apr 15, 2019

The diff seems to include spurious changes which makes it hard to review.

@dpseidel
Copy link
Collaborator

Sorry, yes, I got a little nit picky on the NEWS doc, clearly that should be in a different PR. All cleaned up now.

Copy link
Member

@thomasp85 thomasp85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thanks for finishing it of Dana

@lock
Copy link

lock bot commented Oct 21, 2019

This old issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with reprex) and link to this issue. https://reprex.tidyverse.org/

@lock lock bot locked and limited conversation to collaborators Oct 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants