How to prevent two labels to overlap in a barchart?

ggplot2, r

Solution

You can use a variant of the well-known population pyramid.

Some sample data (code inspired by Didzis Elferts' answer):

set.seed(654)
week <- sample(0:9, 3000, rep=TRUE, prob = rchisq(10, df = 3))
status <- factor(rbinom(3000, 1, 0.15), labels = c("Shipped", "Not-Shipped"))
data.df <- data.frame(Week = week, Status = status)

Compute count scores for each week, then convert one category to negative values:

library("plyr")
plot.df <- ddply(data.df, .(Week, Status), nrow)
plot.df$V1 <- ifelse(plot.df$Status == "Shipped",
                     plot.df$V1, -plot.df$V1)

Draw the plot. Note that the y-axis labels are adapted to show positive values on either side of the baseline.

library("ggplot2")
ggplot(plot.df) + 
  aes(x = as.factor(Week), y = V1, fill = Status) +
  geom_bar(stat = "identity", position = "identity") +
  scale_y_continuous(breaks = 100 *     -1:5, 
                     labels = 100 * c(1, 0:5)) +
  geom_text(aes(y = sign(V1) * max(V1) / 30, label = abs(V1)))

The plot:

For production purposes you'd need to determine the appropriate y-axis tick labels dynamically.

Problem

The image below shows a chart that I created with the code below. I highlighted the missing or overlapping labels. Is there a way to tell ggplot2 to not overlap labels? ``` week = c(0, 1, 1, 1, 1, 2, 2, 3, 4, 5) statuses = c('Shipped', 'Shipped', 'Shipped', 'Shipped', 'Not-Shipped', 'Shipped', 'Shipped', 'Shipped', 'Not-Shipped', 'Shipped') dat <- data.frame(Week = week, Status = statuses) p <- qplot(factor(Week), data = dat, geom = "bar", fill = factor(Status)) p <- p + geom_bar() # Below is the most important line, that's the one which displays the value p <- p + stat_bin(aes(label = ..count..), geom = "text", vjust = -1, size = 3) p ```

Original source