I would like to add %-figures on a filled barplot. Here is the plot with the labels at the wrong places:
Here is the dataframe:
x0 <- expand.grid(grp = c("G1","G2")
, treat = c("T1","T2")
, out = c("out1","out2","out3","out4")
)
set.seed(1234)
x0$n <- round(runif(16,0,1)*100,0)
head(x0)
grp treat out n
1 G1 T1 out1 11
2 G2 T1 out1 62
3 G1 T2 out1 61
4 G2 T2 out1 62
5 G1 T1 out2 86
6 G2 T1 out2 64
Now, I add the sum within grp/treat to the dataframe (using sql, sorry!):
x0 <- sqldf(paste("SELECT a.*, (SELECT SUM(n)"
," FROM x0 b"
," WHERE a.grp = b.grp"
," AND a.treat = b.treat"
," ) tot"
," FROM x0 a"
," ORDER BY a.grp,a.treat,a.out"
)
)
x0$p <- with(x0, n/tot)
x0$p2 <- with(x0, paste(formatC(p*100, digits=2
, format="fg"),"%",sep=""))
head(x0)
grp treat out n tot p p2
1 G1 T1 out1 11 192 0.05729167 5.7%
2 G1 T1 out2 86 192 0.44791667 45%
3 G1 T1 out3 67 192 0.34895833 35%
4 G1 T1 out4 28 192 0.14583333 15%
5 G1 T2 out1 61 160 0.38125000 38%
6 G1 T2 out2 1 160 0.00625000 0.62%
And here is how I get the plot:
ggplot(x0, aes(grp, weight=n)) +
geom_bar(aes(fill = out), position = "fill") +
facet_grid(.~treat) +
scale_y_continuous(labels=percent) +
geom_text(aes(label=p2, y=p))
I could add a new variable to the dataframe with cumulative percentage but I'm wonder if there is a simpler way to add the labels.
To avoid creating the position values yourself, you can use
position = "stack"
ingeom_text
as in this question. As you noted in the comments, the dataset must be ordered by thefill
variable to get the stacks in the correct order to match the bar stacks.You may end up needing to remove the labels below a certain size to remove the overlap seen in the plot above. Something like
geom_text(aes(label = ifelse(p < .05, NA, p2), y = p), position = "stack")
would remove labels for the very small values.