2

The labels on my stacked bar chart do not appear over the correct bars; instead their positions correspond to a reversed bar order.

enter image description here

Example dataset:

library(scales)
library(ggplot2)
types <- c('Mostly Satisfied','Somewhat satisfied','Unsatisfied')
df_summ <- data.frame(cust_type = factor(types, levels=types),
                      cust_count = c(1.2e3, 2.3e3, 3.4e3)
                      )
df_summ$percent_of_file <- df_summ$cust_count/sum(df_summ$cust_count)
df_summ$label_txt <- paste0(df_summ$cust_type,': ',comma(df_summ$cust_count),' (',
                            percent(df_summ$percent_of_file),')')

# I need a dummy value for the x axis
df_summ$group <- 'All customers'

The code for my plot:

ggplot(df_summ,
       aes(x=group, y = cust_count, label=label_txt))+
  geom_bar(aes(fill=cust_type),position='stack',stat='identity')+
  geom_text(size = 4, 
            position = position_stack(vjust = 0.5,
                                  reverse=TRUE) # changing to reverse=FALSE doesn't help
            )+
  scale_fill_manual(values = setNames(c('green','beige','salmon'), types),
                    guide=FALSE
  ) +
  labs( x = NULL,
        y = NULL,
        title = 'Composition of customer base') +
  theme_minimal() +
  theme ( panel.grid.major = element_blank(), 
            panel.grid.minor = element_blank(),
            axis.text.x=element_blank(),
            axis.ticks.x=element_blank(),
            axis.text.y=element_blank(),
            axis.ticks.y=element_blank()
          )

How can I fix the positions of the labels while maintaining the order of the bars?

My question is sort of like this question, but with a bar chart, and the solution (use position_stack()) doesn't help me here.

C8H10N4O2
  • 18,312
  • 8
  • 98
  • 134
  • You use `character` types in your call to `scale_fill_manual`, but you use `factor(types)` in your actual data. Perhaps you should convert them to `factor` initially instead of in just the data? – r2evans Nov 29 '18 at 17:25
  • 1
    The problem is you didn't give the text layer any variables to "stack" on since you put the `fill` aesthetic within `geom_bar()`. You could either move that to the global `aes()` (i.e., in `ggplot()`) OR add something like `aes(group = cust_type)` into `geom_text()`. You do not need to reverse the stacking. – aosmith Nov 29 '18 at 17:25
  • Here's a possible duplicate: https://stackoverflow.com/questions/47699146/out-of-order-text-labels-on-stack-bar-plot-ggplot – aosmith Nov 29 '18 at 17:27
  • 1
    @r2evans thanks for your suggestion. I tried converting them initially, but it did not make a difference. – C8H10N4O2 Nov 29 '18 at 18:06
  • @aosmith that makes sense. Thanks. – C8H10N4O2 Nov 29 '18 at 18:07

1 Answers1

1

I would add fill = cust_type to and remove label = label_txt from the aesthetics of the ggplot(). I would add aes(label = label_txt) to geom_text() and change reverse = TRUE to reverse = FALSE. Then the R-code of your plot should look like the following and hopefully work:

ggplot(
  data = df_summ
  ,aes(
    x = group
    ,y = cust_count
    ,fill = cust_type)) +
geom_bar(
  position = 'stack'
  ,stat = 'identity') +
geom_text(
  aes(label = label_txt)
  ,size = 4
  ,position = position_stack(
    vjust = 0.5
    ,reverse = FALSE)) +
scale_fill_manual(
  values = setNames(
    c('green','beige','salmon')
    ,types)
  ,guide = FALSE) +
labs(
  x = NULL
  ,y = NULL
  ,title = 'Composition of customer base') +
theme_minimal() +
theme(
  panel.grid.major = element_blank()
  ,panel.grid.minor = element_blank()
  ,axis.text.x = element_blank()
  ,axis.ticks.x = element_blank()
  ,axis.text.y = element_blank()
  ,axis.ticks.y = element_blank()); 
Franziska W.
  • 346
  • 2
  • 4