geom_histogram, fractional/bounded data, and boundary parameter

Viewed 117

I want to plot some data that are fractional [0,1] bounded. The default settings in geom_histogram() do not make this nice:

library(tidyverse)

set.seed(1)
d = tibble(
  x = runif(1000)
)

#plot 1
ggplot(d, aes(x)) +
  geom_histogram()
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

So here we see that the end bars are lower height because they cover a range outside the possible data range. We can try to fix this with the boundary which seems like it should work. From the docs:

center, boundary: bin position specifiers. Only one, center or boundary, may be specified for a single plot. center specifies the center of one of the bins. boundary specifies the boundary between two bins. Note that if either is above or below the range of the data, things will be shifted by the appropriate integer multiple of binwidth. For example, to center on integers use binwidth = 1 and center = 0, even if 0 is outside the range of the data. Alternatively, this same alignment can be specified with binwidth = 1 and boundary = 0.5, even if 0.5 is outside the range of the data.

#plot 2
ggplot(d, aes(x)) +
  geom_histogram(boundary = 0)
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

It works for the left side, but strangely the right side now has a block outside the range entirely. There isn't any data out there. Weird. So it must mean the last default bar is started very close to 1, which again means the default bidwidth must have some odd value. The plot says there are 30 bins, so the binwidth must be 1/30. We can also try setting the closed argument, in case that helps:

#plot 3
ggplot(d, aes(x)) +
  geom_histogram(boundary = 0, closed = "left")
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#plot 4
ggplot(d, aes(x)) +
  geom_histogram(boundary = 0, closed = "right")
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#plot 5
ggplot(d, aes(x)) +
  geom_histogram(boundary = 0, binwidth = 1/30)

Setting the binwidth manually fixes the issue, but why is that?

Created on 2021-06-23 by the reprex package (v2.0.0)

0 Answers
Related