Skip to content

geom_histogram stat_bin computation fails if data = 0.25 #3606

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
lizlaw opened this issue Nov 4, 2019 · 2 comments · Fixed by #3613
Closed

geom_histogram stat_bin computation fails if data = 0.25 #3606

lizlaw opened this issue Nov 4, 2019 · 2 comments · Fixed by #3613

Comments

@lizlaw
Copy link

lizlaw commented Nov 4, 2019

Hello, if I try to create a histogram with a vector of 0.25's the stat_bin computation fails (plots an empty plot) with the warning:
Warning message:
Computation failed in stat_bin():
invalid number of intervals.
I am guessing it is something to do with how it calculates the bins if all the data are equal? All other values I have tried are fine.
Cheers

library(ggplot2)
ggplot() + geom_histogram(aes(x= rep(0.25,10))) # Fails
ggplot() + geom_histogram(aes(x= rep(0.15,10))) # Normal
ggplot() + geom_histogram(aes(x= rep(0.35,10))) # Normal
@clauswilke
Copy link
Member

clauswilke commented Nov 5, 2019

Yes, the binning algorithm fails when the data range goes from 0.25 to 0.25. The relevant code is here:

ggplot2/R/bin.R

Lines 82 to 88 in 7f317d4

shift <- floor((x_range[1] - boundary) / width)
origin <- boundary + shift * width
# Small correction factor so that we don't get an extra bin when, for
# example, origin = 0, max(x) = 20, width = 10.
max_x <- x_range[2] + (1 - 1e-08) * width
breaks <- seq(origin, max_x, width)

The following isolates the relevant calculations and shows how they fail when the data value is 0.25. The specific value is linked to the default width of 0.1 when the data has no range.

x_range <- c(0.25, 0.25) # data range
width <- 0.1 # default when data range is 0
boundary <- width / 2 # default if neither edge nor center given
shift <- floor((x_range[1] - boundary) / width)
origin <- boundary + shift * width

# Small correction factor so that we don't get an extra bin when, for
# example, origin = 0, max(x) = 20, width = 10.
max_x <- x_range[2] + (1 - 1e-08) * width
breaks <- seq(origin, max_x, width)

# now we have ended up with a single break, but we need at least two
breaks
#> [1] 0.25
# the reason is that `origin` is equal to the data value
# this happens *only* when the data value is 0.25
origin
#> [1] 0.25

# the same doesn't happen for any other data values
x_range <- c(0.15, 0.15) # data range
width <- 0.1 # default when data range is 0
boundary <- width / 2 # default if neither edge nor center given
shift <- floor((x_range[1] - boundary) / width)
origin <- boundary + shift * width

# Small correction factor so that we don't get an extra bin when, for
# example, origin = 0, max(x) = 20, width = 10.
max_x <- x_range[2] + (1 - 1e-08) * width
breaks <- seq(origin, max_x, width)
breaks
#> [1] 0.05 0.15
origin
#> [1] 0.05

Created on 2019-11-05 by the reprex package (v0.3.0)

Fundamentally, the problem is this correction, which fails in exactly this one case:

ggplot2/R/bin.R

Lines 85 to 88 in 7f317d4

# Small correction factor so that we don't get an extra bin when, for
# example, origin = 0, max(x) = 20, width = 10.
max_x <- x_range[2] + (1 - 1e-08) * width
breaks <- seq(origin, max_x, width)

I think the solution is to add the following immediately after:

if (length(breaks) == 1) {
  breaks <- c(breaks, breaks + width)
}

clauswilke added a commit to wilkelab/ggplot2_archive that referenced this issue Nov 5, 2019
clauswilke added a commit that referenced this issue Nov 6, 2019
@lock
Copy link

lock bot commented May 5, 2020

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 May 5, 2020
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 a pull request may close this issue.

2 participants