lionel- / ggstance

Horizontal ggplot2 components
201 stars 20 forks source link

Would it be possible to add an hjust argument to position_stackv to automate text label positioning in stacked horiztonal bar plots? #17

Closed eipi10 closed 6 years ago

eipi10 commented 7 years ago

Here's a reprex:

Summarize data for plot:

library(tidyverse)
library(ggstance)

dat = mtcars %>% group_by(vs, carb, am) %>% 
  tally %>% 
  mutate(pct=n/sum(n))

In the plot below, we use position=position_stack(vjust=0.5) to center the labels within each section of the stacked bars, and we use scales="free_x", space="free_x" to avoid blank spaces for empty x-axis levels.

ggplot(dat, aes(x=factor(carb), y=pct, fill=factor(am))) +
  geom_bar(stat='identity') + 
  geom_text(aes(label=sprintf("%1.1f", pct*100)), colour="white", position=position_stack(vjust=0.5)) +
  scale_y_continuous(labels=percent) +
  facet_grid(. ~ vs,  scales="free_x",  space="free_x")

If I want this to be a horizontal bar plot, the natural approach would be to add coord_flip, as in the code below. However, with coord_flip, scales="free_x", space="free_x" no longer removes the space for the empty levels.

ggplot(dat, aes(x=factor(carb), y=pct, fill=factor(am))) +
  geom_bar(stat='identity') + 
  geom_text(aes(label=sprintf("%1.1f", pct*100)), colour="white", position=position_stack(vjust=0.5)) +
  scale_y_continuous(labels=percent) +
  facet_grid(. ~ vs, scales="free_x", space="free_x") +
  coord_flip()

An alternative would be to use geom_barh from ggstance as in the code below. However, position=position_stackv(hjust=0.5) doesn't work, because position_stackv doesn't take an hjust argument. It would be nice to have the hjust argument available so that the text labels can be centered within each bar portion.

ggplot(dat, aes(x=pct, y=factor(carb), fill=factor(am))) +
  geom_barh(stat='identity') + 
  geom_text(aes(label=sprintf("%1.1f", pct*100)), colour="white", position=position_stackv(hjust=0.5)) +
  scale_x_continuous(labels=percent) +
  facet_grid(vs ~ ., scales="free_y", space="free_y")

I realize I can set the label x-values when I summarize the data, as in the code below, but it would be nice to just be able to do position=position_stackv(hjust=0.5) just as we can do position=position_stack(vjust=0.5) in the vertical bar plot.

dat = mtcars %>% group_by(vs, carb, am) %>% 
  tally %>% 
  mutate(pct = n/sum(n)) %>% 
  arrange(desc(am), pct) %>% 
  mutate(xval = cumsum(pct) - 0.5*pct)

ggplot(dat, aes(x=pct, y=factor(carb), fill=factor(am))) +
  geom_barh(stat='identity') + 
  geom_text(aes(label=sprintf("%1.1f", pct*100), x=xval), colour="white") +
  scale_x_continuous(labels=percent) +
  facet_grid(vs ~ ., scales="free_y", space="free_y")
eipi10 commented 6 years ago

Thanks Lionel!