rggplot2

ggplot: Extending axis ticks and putting boxes around axis items


This visualization shows the distribution of responses and the prompt text for a collection of Likert (agree/disagree) items. I'd like to make it a little easier for readers to connect the prompt text to the corresponding bar, by putting a box around each prompt and extending the axis tick mark to the appropriate box. enter image description here


Solution

  • One option to achieve your desired result would be to use ggtext::element_markdown which allows to draw a box around the axis text. Note however, that this requires to use a <br> tag to add line breaks instead of \n.

    Using some fake example data:

    library(ggplot2)
    library(ggtext)
    
    set.seed(123)
    
    dat <- data.frame(
      x = 1:12,
      y = sapply(1:12, \(x) lorem::ipsum_words(12))
    )
    
    p <- ggplot(dat) +
      geom_col(
        aes(x, y)
      ) +
      scale_y_discrete(
        labels = \(x) label_wrap_gen()(x) |> gsub("\\n", "<br>", x = _),
        guide = guide_axis(n.dodge = 2)
      ) +
      theme(
        axis.text.y = ggtext::element_markdown(
          box.color = "black",
          linetype = 1,
          padding = unit(2, "pt"),
          linewidth = .25
        )
      )
    

    For the axis ticks you can use a vector to get ticks of different lengths as suggested by @Axeman

    p +
      theme(
        axis.ticks.length.y = rel(c(3, 50))
      )
    

    or as a second option use e.g. annotate to fake the axis ticks using a geom_segment which however requires some fiddling to get the lengths right:

    p +
      annotate(
        "segment",
        x = 0, xend = -5,
        y = seq(2, 12, 2),
        yend = seq(2, 12, 2),
        linewidth = .5
      ) +
      coord_cartesian(
        clip = "off", xlim = c(0, NA), expand = FALSE
      )