Use data from after_stat in ggplot to control label position of stacked bars

Viewed 49

Earlier I asked a question on how to make a horizontal stacked bar chart here: ggplot stacked bar chart in horizontal direction. What is the influence of the y-aesthetic?

The awesome tip is to set orientation=y so that the default guessing from ggplot does not happen when I set y=1in the y-aesthetics.

Now I run into the problem that I stack the bars, but the x-positioning does not work. Precisely I mean the following:

With that data

structure(list(names = c("v1", "v2"), count = c(55L, 17L), share = c(0.76, 
0.24), label = c("76 %", "24 %"), color = c("#df91a3", "#A5AA99"
)), row.names = c(NA, -2L), class = "data.frame")

  names count share label   color
1    v1    55  0.76  76 % #df91a3
2    v2    17  0.24  24 % #A5AA99

I can create this plot now:

  p1 = ggplot(df, aes(y = 1,
                      x = .data[["share"]])) +
    geom_col(
      position = position_stack(),
      color = "black",
      fill = df$color,
      orientation = "y"
    ) +
    scale_fill_identity() +
    geom_text(aes(
      label = names),
      position = position_stack(),
      size = 7
    ) 

enter image description here

However, the values for the labels do not get stacked. It appears that v2 is the larger group and v1the smaller. So I could compute the x-values for id advanced, but I guess there might be a better way to do this directly in ggplot.

When I call:

b = b = ggplot_build(p1)
b$data

[[1]]
     x y PANEL group flipped_aes xmin xmax ymin ymax colour    fill size linetype alpha
1 0.76 1     1    -1        TRUE 0.00 0.76 0.55 1.45  black #df91a3  0.5        1    NA
2 1.00 1     1    -1        TRUE 0.76 1.00 0.55 1.45  black #A5AA99  0.5        1    NA

[[2]]
     x   y      label PANEL group ymax xmin xmax ymin colour size angle hjust vjust alpha family fontface lineheight
1 0.76 0.5 master\n\n     1    -1    1 0.76 0.76    0  black    7     0   0.5   0.5    NA               1        1.2
2 0.24 0.5  other\n\n     1    -1    1 0.24 0.24    0  black    7     0   0.5   0.5    NA               1        1.2

So in theory I just want from the first list item (the data for the bars) the value x/2 plus all the preceeding vaues of x. So I thought I might could access this in a call to after_stat, but I am really not sure if this is the way to go...

1 Answers

I think in this case it would be easier to explicitly flip the co-ordinates:

ggplot(df, aes(x = 1, y = share, fill = color)) +
    geom_col(
      position = position_stack(),
      color = "black",
      orientation = "x"
    ) +
    scale_fill_identity() +
    geom_text(aes(
      label = names),
      position = position_stack(vjust = 0.5),
      size = 7
    ) +
  scale_x_continuous(limits = c(0, 2)) +
  coord_flip()

enter image description here

Related