Consider this simple example
library(ggplot2)
dat <- data.frame(number = c(5, 10, 11 ,12,12,12,13,15,15))
ggplot(dat, aes(x = number)) + geom_histogram()
See how the bars are weirdly aligned with the x axis? Why is the first bar on the left of 5.0
while the bar at 10.0
is centered? How can I get control over that? For instance, it would make more sense (to me) to have the bar starting on the right of the label.
Thanks!
Why are the bars "weirdly aligned"?
Let me start by explaining, why your code leads to weirdly aligned bars. This has to do with the way a histogram is constructed. First, the x-axis is split up into intervals and then, the number of values in each interval is counted.
By default,
ggplot
splits the data up into 30 bins. It even spits out a message that says so:The default number of is not always a good choice. In your case, where all the data points are integers, one might want to choose the boundaries of the bins as
5, 6, 7, 8, ...
or4.5, 5.5, 6.5, ...
, such that each bin contains exactly one integer value. You can obtain the boundaries of the bins that have been used in the plot as follows:As you can see, the boundaries of the bins are not chosen in a way that would lead to a nice alignment of the bars with integers.
So, in short, the reason for the weird alignment is that
ggplot
simply uses a default number of 30 bins, which is not suitable, in your case, to have bars that are nicely aligned with integers.There are (at least) two ways to get nicely aligned bars that I will discuss in the following
Use a bar plot instead
Since you have integer data, a histogram may just not be the appropriate choice of visualisation. You could instead use
geom_bar()
, which will lead to bars that are centered on integers:You could move the bars to the right of the integers by adding
0.5
tonumber
:Create a histogram with appropriate bins
If you nevertheless want to use a histogram, you can make ggplot to use more reasonable bins as follows:
With
binwidth = 1
, you override the default choice of 30 bins and explicitly require that bins should have a width of 1.boundary = 0
ensures that the binning starts at an integer value, which is what you need, if you want the integers to be to the left of the bars. (If you omit it, bins are chosen such that the bars are centered on integers.)The argument
closed = "left"
is a bit more tricky to explain. As I described above, the boundaries of the bins are now chosen to be5, 6, 7, ...
. The question is now, in which bin, e.g., 6 should be? It could be either the first or second one. This is the choice that is controlled byclosed
: if you set it to"right"
(the default), then the bins are closed on the right, meaning that the right boundary of the bin will be included, while the left boundary belongs to the bin to the left. So, 6 would be in the first bin. On the other hand, if you chose"left"
, the left boundary will be part of the bin and 6 would be in the second bin.Since you want the bars to be to the left of the integers, you need to pick
closed = "left"
.Comparison of the two solutions
If you compare the histogram with the bar plot, you will notice two differences:
geom_bar(width = 1)
.This will center the bar on the value
Here is a trick with the tick label to get the bar align on the left.. But if you add other data, you need to shift them also
other option:
binwidth = 1, breaks=seq(0.5,15.5,1)
(might make more sense for integer)