Skip to content

breaks = NULL drops axis altogether #2983

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

Closed
ptoche opened this issue Nov 6, 2018 · 5 comments · Fixed by #3257
Closed

breaks = NULL drops axis altogether #2983

ptoche opened this issue Nov 6, 2018 · 5 comments · Fixed by #3257
Labels
bug an unexpected problem or unintended behavior
Milestone

Comments

@ptoche
Copy link

ptoche commented Nov 6, 2018

Setting breaks = NULL, to remove axis tick marks and labels, results in the axis being dropped altogether. I don't remember seeing this before. Is this an intended feature?

library(reprex)

library(ggplot2)
ggplot(data = NULL, aes(x = c(-3, 3))) + 
    stat_function(fun = function(x) dnorm(x, 0, 1)) + 
    scale_x_continuous(breaks = NULL) +
    theme_classic() 

reprex() 
#> Rendering reprex...
#> Rendered reprex is on the clipboard.

Created on 2018-11-07 by the reprex package (v0.2.0).

@ptoche
Copy link
Author

ptoche commented Nov 7, 2018

I have not looked at the code (note to self: look at the code), but could this be related to this other case of the missing axis?

#2970

@clauswilke
Copy link
Member

No, it‘s two separate issues. The other issue is simply caused by the discrete scale only placing breaks at discrete values found in the data, which is correct behavior I think.

@ptoche
Copy link
Author

ptoche commented Nov 10, 2018

Thanks for the feedback Claus. So I think I've got something. Please let me know what you think.

The first argument of the guide_axis function in "guides-axis.r" returns zeroGrob() if at has length zero, which it is the case if we set breaks = NULL.

The code copied below makes it clear why breaks = NULL and breaks = numeric(0) have the same effect:

    guide_axis <- function(at, labels, position = "right", theme) {
      if (length(at) == 0) {
            return(zeroGrob())
     }

Now, two things. How to fix this issue such that breaks = NULL results in breaks and labels being removed, but the axis being kept? Secondly, when was this break introduced and was it intended?

Line 7 of 2363611#diff-348ffaa265a58dc2db9470750b00523bL7

Hadley changed NA to NULL (among other changes). I briefly experimented with interpreting NULL breaks as NA and a simple example worked as expected. I have not, however, tested further, as it's possible that Hadley's change was intended. In "guides-axis.r", change lines 7-10 to the following:

    if (length(at) == 0) {
        at <- NA; print("I'm line 9 in guides-axis.r");  
        #return(zeroGrob())
    }

Above I bypass returning zeroGrob() entirely. It fits my expectation that removing breaks should not remove the axis line. To keep the ability to remve the axis line, without going through a theme, we could add a variable like axis that could be set to null with axis = NULL inside the scale_*_* funtions. Or show.axis = FALSE or something like that.

As a side comment, while exploring the code I noticed that a break_info function is defined multiple times. Isn't that supposed to be a bad idea? Below are the places where it occurs, in slightly different guises, but with pretty much the same purpose:

  • scale-.r, line 317
  • scale-continuous.r, line 126
  • scale-date.r, line 335
  • axis-secondary.R, line 151

While I use ggplot2 nearly every day, I've never looked very long inside the hood and there's much of the structure that is a complete mystery to me. I had a few minutes to spare...

Here the only example I have tested:

df = data.frame(x = 0:100, y = 0:100)
ggplot(df, aes(x, y)) + geom_point() +
    scale_y_continuous(breaks = NULL) +
    theme_classic() +
    theme(axis.line.x = element_line(color="red", size = 2),
          axis.line.y = element_line(color="blue", size = 2))

@ptoche
Copy link
Author

ptoche commented Nov 21, 2018

What do we mean when we set breaks to NULL?

It seems to me that setting "breaks = NULL" ought to remove the axis ticks and labels, but NOT the axis itself. It seems to me that the appearance of the axis lines (including their possible invisibility) ought to be controlled within the theme functions.

As I recall it and as illustrated by various stackoverflow discussions, the old behaviour was to remove tick marks and labels, but not the line. See e.g. this question from 2010 (ancient history): https://stackoverflow.com/questions/2678141/. Remark: There is one example from the current PDF manual that gives a clear indication that setting "breaks = NULL" is intended to remove the axis. It is in the section on the (otherwise pretty much broken) geom_dotplot() (currently, page 67). Elsewhere in the manual, it is not explained so clearly what "breaks = NULL" is intended to achieve.

Moreover, it seems to me that the usage of "breaks = NULL" ought to be more consistent across different geoms/scales/stats. Currently the behaviour of "breaks = NULL" is to remove the axis when it is set inside a scale_*_*()'' function, but it doesn't do anything when it is set inside the stat_bin() function (here the breaks optional argument is intended to allow the user to override the default computations, with default set to "breaks = NULL").

Suggestion 1: replace the default "breaks = NULL" inside stat_bin() to "breaks = NA" (simple change of the check from is.null to is.na).

Suggestion 2: change the default behaviour of "breaks = NULL" from suppressing the entire axis to suppressing only the ticks and labels.

Any opinion?

library(ggplot2)
theme_set(theme_classic()). # to show the axes, if any

# Set breaks = NULL inside scale_y_continuous, current behaviour: one example in the PDF documentation:
# From manual page 67, Examples of geom_dotplot 
# y axis isn't really meaningful, so hide it
ggplot(mtcars, aes(x = mpg)) + geom_dotplot(binwidth = 1.5) +
    scale_y_continuous(NULL, breaks = NULL)

# In stat_bin(), the default is "breaks = NULL" 

# Default
ggplot(mtcars, aes(x = mpg)) + stat_bin() 

# Set breaks = NULL: does not suppress axis, neither does it suppress labels
ggplot(mtcars, aes(x = mpg)) + stat_bin(breaks = NULL) 

# Set breaks = NA: seems like NA ought to be a workable alternative to NULL
ggplot(mtcars, aes(x = mpg)) + stat_bin(breaks = NA) 
#> Error: <text>:3:27: unexpected symbol
#> 2: library(ggplot2)
#> 3: theme_set(theme_classic()).
#>                              ^

Created on 2018-11-21 by the reprex package (v0.2.0).

@thomasp85 thomasp85 added the bug an unexpected problem or unintended behavior label Apr 11, 2019
@thomasp85 thomasp85 added this to the ggplot2 3.2.0 milestone Apr 11, 2019
@lock
Copy link

lock bot commented Oct 20, 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 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug an unexpected problem or unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants