I am trying to plot nice stacked percent barchart
using ggplot2
. 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 barplot where each stack is scaled to sum to 100%
R stacked percentage bar plot with percentage of binary factor and labels (with ggplot)
My problem is that I can't place labels
where I want - in the middle of the bars.
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:
How to place labels in the midde of the bars (areas)
How to plot not all the labels, but for example which are greather than 10%?
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.
library('plyr') library('ggplot2') library('scales') set.seed(1992) n=68 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())+ coord_flip()+ scale_y_continuous(labels = percent_format())+ ylab("")+ xlab("")
Under Chart Tools, on the Design tab, in the Data group, click Select Data. In the Select Data Source dialog box, in the Legend Entries (Series) box, click the data series that you want to change the order of. Click the Move Up or Move Down arrows to move the data series to the position that you want.
plot. bar(stacked=True) , or pandas. DataFrame. plot(kind='bar', stacked=True) , is the easiest way to plot a stacked bar plot.
A stacked bar chart is used to show the total or average of each category. The taller a bar is, the larger the volume of those numeric values. The bars in the stacked bar chart below show how each category compares to the average. The bottom bar shows the total for all of the categories.
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:
library(dplyr) # Initial data frame df <- data.frame(Category, Brand, USD) # Calculate percentages 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))
With ggplot2 version 2, it is no longer necessary to calculate the coordinates of the text labels to get them centered. Instead, you can use position=position_stack(vjust=0.5)
. For example:
ggplot(df.summary, aes(x=reorder(Brand, USD, sum), 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),"%"),"")), position=position_stack(vjust=0.5), colour="white") + coord_flip() + scale_y_continuous(labels = percent_format()) + labs(y="", x="")
With older versions, we need to calculate the position. (Same as above, but with an extra line defining pos
):
# 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)
Then plot the data using 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="")
I followed the example and found the way how to put nice labels for simple stacked barchart. I think it might be usefull too.
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( pos = cumsum(USD)-0.5*USD) ggplot(df.summary, aes(x=reorder(Brand,USD,function(x)+sum(x)), y=USD, fill=Category)) + geom_bar(stat='identity', width = .7, colour="black", lwd=0.1) + geom_text(aes(label=ifelse(USD>100,round(USD,0),""), y=pos), colour="white") + coord_flip()+ labs(y="", x="")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With