Showing data values on stacked bar chart in ggplot2
Solution 1
From ggplot 2.2.0
labels can easily be stacked by using position = position_stack(vjust = 0.5)
in geom_text
.
ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
geom_bar(stat = "identity") +
geom_text(size = 3, position = position_stack(vjust = 0.5))
Also note that "position_stack()
and position_fill()
now stack values in the reverse order of the grouping, which makes the default stack order match the legend."
Answer valid for older versions of ggplot
:
Here is one approach, which calculates the midpoints of the bars.
library(ggplot2)
library(plyr)
# calculate midpoints of bars (simplified using comment by @DWin)
Data <- ddply(Data, .(Year),
transform, pos = cumsum(Frequency) - (0.5 * Frequency)
)
# library(dplyr) ## If using dplyr...
# Data <- group_by(Data,Year) %>%
# mutate(pos = cumsum(Frequency) - (0.5 * Frequency))
# plot bars and add text
p <- ggplot(Data, aes(x = Year, y = Frequency)) +
geom_bar(aes(fill = Category), stat="identity") +
geom_text(aes(label = Frequency, y = pos), size = 3)
Solution 2
As hadley mentioned there are more effective ways of communicating your message than labels in stacked bar charts. In fact, stacked charts aren't very effective as the bars (each Category) doesn't share an axis so comparison is hard.
It's almost always better to use two graphs in these instances, sharing a common axis. In your example I'm assuming that you want to show overall total and then the proportions each Category contributed in a given year.
library(grid)
library(gridExtra)
library(plyr)
# create a new column with proportions
prop <- function(x) x/sum(x)
Data <- ddply(Data,"Year",transform,Share=prop(Frequency))
# create the component graphics
totals <- ggplot(Data,aes(Year,Frequency)) + geom_bar(fill="darkseagreen",stat="identity") +
xlab("") + labs(title = "Frequency totals in given Year")
proportion <- ggplot(Data, aes(x=Year,y=Share, group=Category, colour=Category))
+ geom_line() + scale_y_continuous(label=percent_format())+ theme(legend.position = "bottom") +
labs(title = "Proportion of total Frequency accounted by each Category in given Year")
# bring them together
grid.arrange(totals,proportion)
This will give you a 2 panel display like this:
If you want to add Frequency values a table is the best format.
MYaseen208
Updated on August 09, 2020Comments
-
MYaseen208 almost 4 years
I'd like to show data values on stacked bar chart in ggplot2. Here is my attempted code
Year <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4)) Category <- c(rep(c("A", "B", "C", "D"), times = 4)) Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251) Data <- data.frame(Year, Category, Frequency) library(ggplot2) p <- qplot(Year, Frequency, data = Data, geom = "bar", fill = Category, theme_set(theme_bw())) p + geom_text(aes(label = Frequency), size = 3, hjust = 0.5, vjust = 3, position = "stack")
I'd like to show these data values in the middle of each portion. Any help in this regard will be highly appreciated. Thanks
-
Tyler Rinker over 10 yearsRelated question: stackoverflow.com/questions/18994631/…
-
geotheory over 9 yearsNot really the place for a debate, but I wonder if it's possible to be overly prescriptive about this, particularly for the more general audience. This is a nice example - numbers denote percentages that can be remembered, which removes the need for a scale that less numerically-literate readers might find less accessible?
-
-
atomicules about 12 yearsThanks for this answer. I used it to do similar using
data.table
instead ofplyr
, so something like this:Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]
-
Pablo Olmos de Aguilera C. about 5 yearsIs there anyway to add the frequency total too?