How to align caption text with left bar in a bar chart?

Viewed 176

I am trying to align the caption text in a bar chart, so that it will start at the same vertical margin as the left bar.

library(ggplot2)
library(tibble)

my_df <- 
  tibble::tribble(~response, ~estimate,
                  "little_bit", 0.353477,
                  "no", 0.307639,
                  "very", 0.338883)

ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
  geom_bar(stat = "identity", width = 0.9, fill = "royalblue") +
  ggtitle("do you like swimming with fish?") +
  ylab("") +
  labs(caption = "this is my caption") +
  theme_minimal() +
  theme(
    axis.line.x = element_blank(),
    axis.line.y = element_blank(),
    axis.text.y = element_blank(),
    panel.grid  = element_blank(),
    panel.grid.major=element_blank(),
    plot.title = element_text(hjust = 0.5, size = 26),
    axis.text.x = element_text(angle = 0, size = 14, margin = margin(t = 0, r = 20, b = 0, l = 0)),
    axis.title.x = element_blank(),
    legend.title = element_blank(),
    plot.caption = element_text(hjust = 0, size = 8),
    plot.caption.position = "plot") ## <-- I thought this would help, but no...

barchart


Is there a way to align the caption such as the following?


aligned

2 Answers

To get your desired result set the caption position to "panel" and remove the expansion of the x-scale:

library(ggplot2)
library(tibble)

my_df <- 
  tibble::tribble(~response, ~estimate,
                  "little_bit", 0.353477,
                  "no", 0.307639,
                  "very", 0.338883)

ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
  geom_bar(stat = "identity", width = 0.9, fill = "royalblue") +
  ggtitle("do you like swimming with fish?") +
  scale_x_discrete(expand = c(0, 0)) +
  labs(caption = "this is my caption", y = NULL) +
  theme_minimal() +
  theme(
    axis.line.x = element_blank(),
    axis.line.y = element_blank(),
    axis.text.y = element_blank(),
    panel.grid  = element_blank(),
    panel.grid.major=element_blank(),
    plot.title = element_text(hjust = 0.5, size = 26),
    axis.text.x = element_text(angle = 0, size = 14, margin = margin(t = 0, r = 20, b = 0, l = 0)),
    axis.title.x = element_blank(),
    legend.title = element_blank(),
    plot.caption = element_text(hjust = 0, size = 8),
    plot.caption.position = "panel") 

Or, a very common workaround for those cases would be to annotate outside of the plot area. (I am using annotate(geom = "text",...) - you could also use geom_text, but you would only need a data frame for it.)

I personally prefer the annotate option as it is more versatile and generalisable for other purposes as well.

library(ggplot2)

my_df <-
  tibble::tribble(  ~response, ~estimate,  "little_bit", 0.353477,  "no", 0.307639,  "very", 0.338883)

barwidth <- 0.9

ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
  geom_bar(stat = "identity", width = barwidth, fill = "royalblue") +
  annotate(
    geom = "text",
    x = 1 - barwidth / 2, hjust = 0, # that's the trick 
    y = -0.1, # play around with y. you could also set it relativ to your bar heights
    label = "this is my caption"
  ) +
  coord_cartesian(clip = "off", ylim = c(0, NA)) + # necessary to set axis limits and clip off to annotate beyond
  ggtitle("do you like swimming with fish?") +
  theme_minimal() +
  theme(plot.margin = margin(b = 1, unit = "inch")) # margin randomly chosen. unfortunately also necessary

Related