Reputation: 353
When I add a label annotation of bin height of a histogram, the bins shift height from the same plot without the annotation.
I manually added in the labels and it works until the last value is added for the last bin.
p2 <- ggplot(airquality)+
geom_histogram(aes(x=Temp),bins=9,color="black",fill="white")+
theme_classic()
p2 # correct plot without annotations
pg <- ggplot_build(p2)
pgx <- pg$data[[1]]$x # extract x values of bin centers
pgy <- pg$data[[1]]$y # extract y values of bins
# plot with label annotations at the x and y positions
p3 <- ggplot(airquality,aes(x=Temp))+
geom_histogram(bins=9,color="black",fill="white")+
theme_classic()+
annotate("label",x=pgx,y=pgy,label=pgy)
p3
# bins are shifted a bit left and bin heights have been altered
# try to type locations and labels manually
p4 <- ggplot(airquality,aes(x=Temp))+
geom_histogram(bins=9,color="black",fill="white")+
theme_classic()+
annotate("label",
x=c(56.375, 61.5,66.625,71.75,76.875,82,87.125,92.25,97.375),
y=c(6, 10,16,16,32,34,22,15,2),
label=c(6, 10,16,16,32,34,22,15,2))
p4
# same plot as p3
# try to type locations and labels manually but without last label
p5 <- ggplot(airquality,aes(x=Temp))+
geom_histogram(bins=9,color="black",fill="white")+
theme_classic()+
annotate("label",
x=c(56.375, 61.5,66.625,71.75,76.875,82,87.125,92.25),
y=c(6, 10,16,16,32,34,22,15),
label=c(6, 10,16,16,32,34,22,15))
p5
# the plot needed but missing the last bin label
How do I get the correct histogram with all annotations?
Upvotes: 0
Views: 280
Reputation: 66955
This seems to work, but I'm not sure exactly why it sidesteps the alignment issues introduced from using geom_histogram
for the first layer.
ggplot(data = airquality, aes(Temp, label = ..count..)) +
stat_bin(geom = "bar", color="black", fill="white", bins = 9) +
stat_bin(geom = "label", bins = 9) +
theme_classic()
Upvotes: 1
Reputation: 6954
The problem here is in the "reactiveness" of geom_histogram
and that a ggplot is only rendered when it is called. As soon as the range of the plot is changed, the bins are calculated differently and therefor shift.
I have two solutions for you and I am not very happy with either but here you go:
First: Basically convert your histogram into a barplot:
p1 <- ggplot()+
geom_histogram(aes(x=airquality$Temp), bins=9, color="black", fill="white")+
theme_classic()
p1 # correct plot without annotations
# get values of the histogram
pg1 <- ggplot_build(p1)
pg1x <- pg1$data[[1]]$x # extract x values of bin centers
pg1y <- pg1$data[[1]]$y # extract y values of bins
# mirror the histogram as a barplot
# a barplot is fixed and not responsive like a histogram
p2 <- ggplot() +
geom_bar(aes(x = pg1x, y = pg1y), stat="identity")
# grab the labels and position from the barplot
pg2 <- ggplot_build(p2)
pg2x <- pg2$data[[1]]$x # extract x values of bin centers
pg2y <- pg2$data[[1]]$y # extract y values of bins
# final plot
p2 +
annotate("label",x=pg1x,y=pg1y,label=pg1y)
Second: Define a binwidth
formula rather than bins=
that does not depend on the plot itself. You would have to tweak the formula however to get the same result
p2 <- ggplot(airquality)+
geom_histogram(aes(x=Temp),
binwidth = function(x) 2 * IQR(x) / (length(x)^(1/3)),
color="black",fill="white")+
theme_classic()
p2 # correct plot without annotations
pg <- ggplot_build(p2)
pgx <- pg$data[[1]]$x # extract x values of bin centers
pgy <- pg$data[[1]]$y # extract y values of bins
# plot with label annotations at the x and y positions
p3 <- ggplot(airquality,aes(x=Temp))+
geom_histogram(aes(x=Temp),
binwidth = function(x) 2 * IQR(x) / (length(x)^(1/3)),
color="black",fill="white")+
theme_classic()+
annotate("label",x=pgx,y=pgy,label=pgy)
p3
Upvotes: 0