AK47 AK47 - 10 months ago 41
R Question

How to center stacked percent barchart labels

I am trying to plot nice

stacked percent barchart
. I've read some material and almost manage to plot, what I want. Also, I enclose the material, it might be useful in one place:

How do I label a stacked bar chart in ggplot2 without creating a summary data frame?

Create Stacked percent barplot in R

R stacked percentage bar plot with percentage of binary factor and labels (with ggplot)

My problem is that I can't place
where I want - in the middle of the bars. enter image description here

You can see the problem in the picture above - labels looks awfull and also overlap each other.

What I am looking for right now is:

  1. How to place labels in the midde of the bars (areas)

  2. How to plot not all the labels, but for example which are greather than 10%?

  3. How to solve overlaping problem?

For the
Q 1.
@MikeWise suggested possible solution. However, I still can't deal with this problem.

Also, I enclose reproducible example, how I've plotted this grahp.


Category <- sample(c("Black", "Red", "Blue", "Cyna", "Purple"), n, replace = TRUE, prob = NULL)
Brand <- sample("Brand", n, replace = TRUE, prob = NULL)
Brand <- paste0(Brand, sample(1:5, n, replace = TRUE, prob = NULL))
USD <- abs(rnorm(n))*100

df <- data.frame(Category, Brand, USD)

# Calculate the percentages
df = ddply(df, .(Brand), transform, percent = USD/sum(USD) * 100)

# Format the labels and calculate their positions
df = ddply(df, .(Brand), transform, pos = (cumsum(USD) - 0.5 * USD))

#create nice labes
df$label = paste0(sprintf("%.0f", df$percent), "%")

ggplot(df, aes(x=reorder(Brand,USD,
function(x)+sum(x)), y=percent, fill=Category))+
geom_bar(position = "fill", stat='identity', width = .7)+
geom_text(aes(label=label, ymax=100, ymin=0), vjust=0, hjust=0,color = "white", position=position_fill())+
scale_y_continuous(labels = percent_format())+

Answer Source

Here's how to center the labels and avoid plotting labels for small percentages. An additional issue in your data is that you have multiple bar sections for each colour. Instead, it seems to me all the bar sections of a given colour should be combined. The code below uses dplyr instead of plyr to set up the data for plotting:


# Initial data frame   
df <- data.frame(Category, Brand, USD)

# Calculate percentages and label positions
df.summary = df %>% group_by(Brand, Category) %>% 
  summarise(USD = sum(USD)) %>%   # Within each Brand, sum all values in each Category
  mutate(percent = USD/sum(USD),
         pos = cumsum(percent) - 0.5*percent)

To plot the data, use an ifelse statement to determine whether a label is plotted or not. In this case, I've avoided plotting a label for percentages less than 7%.

ggplot(df.summary, aes(x=reorder(Brand,USD,function(x)+sum(x)), y=percent, fill=Category)) +
  geom_bar(stat='identity',  width = .7, colour="black", lwd=0.1) +
  geom_text(aes(label=ifelse(percent >= 0.07, paste0(sprintf("%.0f", percent*100),"%"),""),
                y=pos), colour="white") +
  coord_flip() +
  scale_y_continuous(labels = percent_format()) +
  labs(y="", x="")

enter image description here