rggplot2label

Center data label in stacked bar plot from ggplot in R + dual-scaled axes


I have such a sample data:

name <- rep(c("ba", "EW", "RW", "Se", "St", "US", "VN"), 2)

value <-  c(0, 6323, 7397, 13945, 11801, 55255, 22519, 4124, 13540, 9616, 57724, 6646, 22021, 8841)

type <- c(rep("g", 7), rep("o", 7))

test <- data.frame(name, value, type)

And have created a plot using the code:

ggplot(test, aes(x=name, y=value, fill=type)) + 
  geom_bar(position = position_stack(reverse = TRUE), stat='identity') + 
  theme(plot.title = element_text(hjust = 0.5)) +
  scale_fill_manual(values = c("#0099f9", "#69c6ff")) + 
  geom_text(aes(label = value), position = position_stack(vjust = 0.5), colour = "black", size = 3) + 
  guides(fill = guide_legend(title = "", reverse = TRUE))

The data labels are not centered in each block: plot

I used the solution from Showing data values on stacked bar chart in ggplot2 and (R) ggplot2 labels not centered properly, but the position = position_stack(vjust = 0.5) in geom_text didn't help

Why is it the case and what else can I do?

Editted: Thanks to Stefan for correcting my solution. One more question is I want to add another Y axis with the data:

name2 <- c("ba", "EW", "RW", "Se", "St", "US", "VN") 
share <- c("100%", "61%", "47%", "80%", "34%", "28%", "28%") 
test2 <- data.frame(name2, share)

So basically they use the same x axis and the share is the percentage from type o / (type g + type o)

I've seen the long discussion whether dual axes makes sense https://www.perceptualedge.com/articles/visual_business_intelligence/dual-scaled_axes.pdf but I just need to have it, how can I do this using ggplot2?


Solution

  • You have to reverse the order of the stack for the labels too, i.e. use position_stack(vjust = 0.5, reverse = TRUE) for geom_text:

    library(ggplot2)
    
    ggplot(test, aes(x = name, y = value, fill = type)) +
      geom_bar(position = position_stack(reverse = TRUE), stat = "identity") +
      theme(plot.title = element_text(hjust = 0.5)) +
      scale_fill_manual(values = c("#0099f9", "#69c6ff")) +
      geom_text(aes(label = value),
        position = position_stack(vjust = 0.5, reverse = TRUE),
        colour = "black", size = 3
      ) +
      guides(fill = guide_legend(title = "", reverse = TRUE))