1
votes

I am trying to make a 100% stacked bar chart in R using ggplot2 and get data labels for the true count, not a percentage. When I try to do that I get tiny bars with just the labels way out on the other side of the graph. I can get a regular bar chart with the counts in the bars and I know there are many questions already on here with how to get the percentages, but I haven't found any answers like what I'm looking for. This is for work, but some mock data would be similar to:

dat <- read.table(text = "assessment User N
missingcomma Sara 5
notcapitolized Sara 2
noindent Sara 1
missingcomma Jason 1
notcapitolized Jason 3
noindent Jason 4
missingcomma Andre 3
notcapitolized Andre 1
noindenet Andre 2", header = TRUE)

With this code I can get the bar chart and data labels:

ggplot(dat, aes(x = assessment, y = N, fill = User)) + 
     geom_bar(stat = "identity") + 
     geom_text(aes(label = N), position = position_stack(vjust = 0.5)) +
     coord_flip()

Bar chart & labels:

And with this code I can get a 100% stacked chart with my labels in the middle of nowhere.

ggplot(dat, aes(x = assessment, y = N, fill = User)) + 
     geom_bar(stat = "identity", position = "fill") + 
     geom_text(aes(label = N), position = position_stack(vjust = 0.5)) +
     coord_flip()

100% Stacked Chart w/ crazy labels:

Please help, it would be much appreciated.

1
Did this answer your question?treysp

1 Answers

0
votes

I think you'll need to calculate the text positions by group, as in the "older versions of ggplot" part of Ramnath's answer here: Showing data values on stacked bar chart in ggplot2.

The ave() function is, for each group in assessment:

  1. Using cumsum() to calculate the total heights of the stacked bars if they weren't position = "fill"
  2. Subtracting each count from that total, shifted by half its value
  3. Normalizing them by the group's total count because the position = "fill" normalizes them to y-axis range [0, 1]



  ggplot(dat) + 
    geom_col(aes(x = assessment, y = N, fill = User), position = "fill") +
    geom_text(aes(x = assessment, 
                  y = ave(dat$N, dat$assessment, 
                          FUN = function(x) (cumsum(x) - 0.5 * x) / sum(x)), 
                  label = N)) +
    coord_flip()

ggplot