2

I am trying to graph the following data:

to_graph <- structure(list(Teacher = c("BS", "BS", "FA"
), Level = structure(c(2L, 1L, 1L), .Label = c("BE", "AE", "ME", 
"EE"), class = "factor"), Count = c(2L, 25L, 28L)), .Names = c("Teacher", 
"Level", "Count"), row.names = c(NA, 3L), class = "data.frame")

and want to add labels in the middle of each piece of the bars that are the percentage for that piece. Based on this post, I came up with:

ggplot(data=to_graph, aes(x=Teacher, y=Count, fill=Level), ordered=TRUE) + 
    geom_bar(aes(fill = Level), position = 'fill') + 
    opts(axis.text.x=theme_text(angle=45)) + 
    scale_y_continuous("",formatter="percent") + 
    opts(title = "Score Distribution") + 
    scale_fill_manual(values = c("#FF0000", "#FFFF00","#00CC00", "#0000FF")) + 
    geom_text(aes(label = Count), size = 3, hjust = 0.5, vjust = 3, position = "stack")

But it

  1. Doesn't have any effect on the graph
  2. Probably doesn't display the percentage if it did (although I'm not entirely sure of this point)

Any help is greatly appreciated. Thanks!

Community
  • 1
  • 1
Jeff Erickson
  • 3,783
  • 8
  • 36
  • 43

1 Answers1

3

The y-coordinate of the text is the actual count (2, 25 or 28), whereas the y-coordinates in the plot panel range from 0 to 1, so the text is being printed off the top.

Calculate the fraction of counts using ddply (or tapply or whatever).

graph_avgs <- ddply(
  to_graph, 
  .(Teacher), 
  summarise, 
  Count.Fraction = Count / sum(Count)
)

to_graph <- cbind(to_graph, graph_avgs$Count.Fraction)

A simplified version of your plot. I haven't bothered to play about with factor orders so the numbers match up to the bars yet.

ggplot(to_graph, aes(Teacher), ordered = TRUE) + 
  geom_bar(aes(y = Count, fill = Level), position = 'fill') + 
  scale_fill_manual(values = c("#FF0000", "#FFFF00","#00CC00", "#0000FF")) + 
  geom_text(
    aes(y = graph_avgs$Count.Fraction, label = graph_avgs$Count.Fraction),  
    size = 3
  )
Jeff Erickson
  • 3,783
  • 8
  • 36
  • 43
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
  • Thanks for your reply. I'm currently getting this error with your code: Error in do.call("layer", list(mapping = mapping, data = data, stat = stat, : object 'Count' not found – Jeff Erickson Nov 23 '11 at 19:38
  • That makes sense, but for some reason when I do the merge, it basically does an outer join on the data. I get structure(list(Teacher = c("BS", "BS", "BS", "BS", "FA"), Level = structure(c(2L, 2L, 1L, 1L, 1L), .Label = c("BE", "AE", "ME", "EE"), class = "factor"), Count = c(2L, 2L, 25L, 25L, 28L), Count.Fraction = c(0.0740740740740741, 0.925925925925926, 0.0740740740740741, 0.925925925925926, 1)), .Names = c("Teacher", "Level", "Count", "Count.Fraction" ), row.names = c(NA, -5L), class = "data.frame") – Jeff Erickson Nov 24 '11 at 22:03
  • I tried adding by="Teacher" but with no luck... Any ideas? Thanks! – Jeff Erickson Nov 24 '11 at 22:04
  • 1
    So, I ended up using cbind instead of merge with only the Count.Fraction column. This gets the data in the correct format for how I worded the question. Then I changed label to the Count.Percentage column to get the percentage rather than the count, as also outlined in my question. Thanks for your help! – Jeff Erickson Nov 25 '11 at 00:05