Search code examples
rggplot2geom-text

Is there an alternative to `orientation = "y"` for `geom_text`?


I'm wondering whether there is a something like or an alternative to orientation="y" for geom_text and whether I missed something?

A simple problem: I want to make a horizontal stacked bar chart using ggplot2 with some additional labels on the right of the bars (e.g. sample size).

To avoid to manually expand the scale or the plot margins to make room for the labels I'm going to use the secondary axis trick, i.e. add the labels via a secondary scale. For that reason I'm using both a continuous x and y scale which requires to explicitly set orientation = "y" in geom_col.

While that works fine I ran into an issue when trying to add labels to the bars using geom_text and position = position_stack(). Unfortunately geom_text does not have an orientation argument. As a result the stacking takes place in the x orientation and the labels do not align with the bars.

A minimal reprex of the issue:

library(ggplot2)

dat <- data.frame(
  y = rep(1:2, each = 2),
  x = c(.2, .8, .8, .2),
  fill = rep(c("A", "B"))
)

ggplot(dat, aes(x, y, fill = fill)) +
  geom_col(orientation = "y") +
  scale_y_continuous(
    breaks = 1:2, labels = c("a", "b"), 
    sec.axis = dup_axis(labels = c("n = 100", "n = 50"))) +
  geom_text(aes(label = x, group = fill),
    orientation = "y",
    position = position_stack(vjust = .5)
  )
#> Warning in geom_text(aes(label = x, group = fill), orientation = "y", position
#> = position_stack(vjust = 0.5)): Ignoring unknown parameters: `orientation`

One option would be to draw the chart in the x orientation and to use good old coord_flip(). However, for my real problem I ran into another issue when using this approach ... but that's a different story. Hence, I'm explicitly looking for a an approach which does not require coord_flip.


Solution

  • The best I could come up with to solve my issue is to use a stat_summary hack which allows to have orientation = "y" with geom="text" and get the labels to be stacked in the same direction as the bars.

    library(ggplot2)
    
    ggplot(dat, aes(x, y, fill = fill)) +
      geom_col(orientation = "y") +
      scale_y_continuous(
        breaks = 1:2, labels = c("a", "b"), 
        sec.axis = dup_axis(labels = c("n = 100", "n = 50"))) +
      stat_summary(aes(label = x, group = fill),
        orientation = "y", fun = \(x) x, geom = "text",
        position = position_stack(vjust = .5)
      )