We can see your problem very clearly by setting up an example that uses facets with very different ranges. There is a single geom_text
layer with nudge_y = 4
:
df <- data.frame(month = factor(c(1:3, 1:3)),
n = c(80, 21, 45, 8, 2, 1),
panel = rep(c("A", "B"), each = 3))
library(ggplot2)
ggplot(df, aes(month, n)) +
geom_col(fill = "deepskyblue4") +
geom_text(aes(label = n), size = 6, nudge_y = 4) +
facet_wrap(.~panel, scales = "free_y") +
scale_y_continuous(expand = expansion(c(0, 0.1))) +
theme_bw(base_size = 16)

Obviously, the y axis scale is smaller on the right, so the 4-unit nudge is proportionately much greater and now doesn't sit nicely on the bars.
One way to solve this is to fix the y axis limits
:
ggplot(df, aes(month, n)) +
geom_col(fill = "deepskyblue4") +
geom_text(aes(label = n), size = 6, nudge_y = 4) +
facet_wrap(.~panel, scales = "free_y") +
scale_y_continuous(limits = c(0, 90), expand = expansion(c(0, 0.1))) +
ylim(c(0, 90)) +
theme_bw(base_size = 16)

However, if you want the bars to fill the plotting area, the easiest way is probably to just use vjust
instead of nudge_y
. Remember, you need a negative vjust
to shift the text upwards.
ggplot(df, aes(month, n)) +
geom_col(fill = "deepskyblue4") +
geom_text(aes(label = n), size = 6, vjust = -0.5) +
facet_wrap(.~panel, scales = "free_y") +
scale_y_continuous(expand = expansion(c(0, 0.1))) +
theme_bw(base_size = 16)

Created on 2022-11-12 with reprex v2.0.2