rggplot2

How to fix inconsistent justification of wrapped labels in geom_label


Here's some data.

library(ggplot2)
df <- structure(list(date = structure(c(18851, 19958, 18933, 18949, 
                                        18976, 19074, 19304, 19570, 19713, 19766, 20032), class = "Date"), 
                     event = c("Census data released", "Johnson v. WEC filed in state court", 
                               "People's Map Commission releases final proposal", "Gov. Evers vetoes maps", 
                               "SCOWIS receives proposed maps", "SCOTUS rules Evers' map unconstitutional", 
                               "Election held using legislature's map", "Protasiewicz begins term", 
                               "SCOWIS strikes down existing maps & invites proposals", 
                               "Legislature passes Evers' map", "Election held using Evers' map"
                     )), row.names = c(NA, -11L), class = c("tbl_df", "tbl", "data.frame"
                     ))

I plot it like this.

df |>
  ggplot(aes(x = 0, y = date)) +
  geom_line() +
  geom_point() +
  ggrepel::geom_label_repel(aes(label = str_wrap(event, 30)),
                            hjust = -0.2, direction = "y", seed = 3)

example image

Notice how the second line of the labels, when wrapped, is inconsistently aligned with the first row of text.

How can I make subsequent lines of a wrapped label begin with the same justification as the first line of the label?

Note: I use ggrepel::geom_label_repel for clarity's sake, but the same wrapping behavior is shown with ggplot2::geom_label.


Solution

  • hjust values outside [0, 1] are not officially supported (AFAIK) and can lead to weirdness, such as in this case. Use hjust = 0 and then use e.g. nudge_x to nudge the position to the right, or tweak those parameters to get what you want.

    Basically, you should use the position to get what you want, not the justification.

    df |>
      ggplot(aes(x = 0, y = date)) +
      geom_line() +
      geom_point() +
      ggrepel::geom_label_repel(
        aes(label = str_wrap(event, 30)), 
        hjust = 0, nudge_x = 1, direction = "y", seed = 3
      )
    

    enter image description here