I am working on a stacked bar chart that illustrates cumulative percentages.
I would like to show the percentage values on the bars, though need them to be spaced such that they don't overlap, but are still intuitively associated with their relevant parts of the bar. This means putting a minimum buffer between labels, but otherwise placing them in their relevant section of the bar.
Here is a dput()
of the data used to produce the below figure:
data<-structure(list(dimension = structure(c(6L, 6L, 6L, 6L, 6L, 6L,
6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L,
6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L,
6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c("Achievement",
"Connection", "Leadership", "Lifestyle", "Partnership", "Support"
), class = "factor"), area = structure(c(21L, 21L, 24L, 24L,
23L, 23L, 23L, 18L, 18L, 18L, 15L, 15L, 21L, 21L, 24L, 24L, 23L,
23L, 23L, 18L, 18L, 18L, 15L, 15L, 21L, 21L, 24L, 24L, 23L, 23L,
23L, 18L, 18L, 18L, 15L, 15L, 21L, 21L, 24L, 24L, 23L, 23L, 23L,
18L, 18L, 18L, 15L, 15L), .Label = c("Appreciation", "Balance",
"Belonging", "Brand Passion", "Burnout", "Care", "Communication",
"Competence", "Consultation", "Family and Social Support", "Financial Performance",
"Forward Vision", "Fulfilment", "Harmony", "Innovation", "Integrity",
"Leadership Commitment", "Marketing Support", "Optimism", "Participation",
"Practical Support", "Satisfied Expectations", "Systems", "Training"
), class = "factor"), label = structure(c(31L, 32L, 43L, 50L,
6L, 55L, 33L, 42L, 41L, 4L, 45L, 44L, 31L, 32L, 43L, 50L, 6L,
55L, 33L, 42L, 41L, 4L, 45L, 44L, 31L, 32L, 43L, 50L, 6L, 55L,
33L, 42L, 41L, 4L, 45L, 44L, 31L, 32L, 43L, 50L, 6L, 55L, 33L,
42L, 41L, 4L, 45L, 44L), .Label = c("Able to contribute views",
"Achieving desired lifestyle", "Believe profits will grow", "Brand helps us compete",
"Business provides flexibility", "Business systems improve productivity",
"Can discuss differences openly", "Decisions have long-term focus",
"Enjoy running the business", "Expectations have been met", "Family positive about the business",
"Family supportive of the business", "Feel connected to other Franchisees",
"Feel informed on important issues", "Feel optimistic about future",
"Feel part of community", "Feel we belong to group", "Financial security has improved",
"Franchisees are appreciated", "Franchisees are recognised",
"Franchisees are respected", "Franchisor cares about our profits",
"Franchisor cares about our success", "Franchisor is competent",
"Franchisor is fair", "Franchisor is professional", "Franchisor is transparent",
"Franchisor is trustworthy", "Franchisor listens to Franchisees",
"Get involved in new initiatives", "Get practical support", "Get relevant support",
"Have access to useful data", "Have confidence in Franchisor",
"Have work satisfaction", "Leadership committed to future", "Long term goals exist",
"Love the brand", "Make a meaningful contribution", "Making a reasonable profit",
"Marketing attracts customers", "Marketing benefits the business",
"Meetings are motivating", "Network is adapting to market", "Network is innovative",
"No serious conflict with Franchisor", "Not emotionally drained by business",
"Not hassled by the business", "On track for financial success",
"Ongoing opportunities to upskill", "Participate in meetings & events",
"Processes exist to resolve conflict", "Proud of reputation",
"Share ideas for improvement", "There is a proven business model",
"There is clear future direction", "There is strategy to protect future",
"Would buy franchise again"), class = "factor"), variable = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,
3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), .Label = c("SD",
"D", "A", "SA"), class = "factor"), value = c(6.98, 9.09, 15.56,
6.82, 2.44, 6.67, 6.67, 11.36, 4.44, 11.36, 17.78, 2.33, 41.86,
43.18, 35.56, 50, 41.46, 28.89, 40, 20.45, 24.44, 20.45, 64.44,
20.93, 48.84, 47.73, 44.44, 40.91, 53.66, 55.56, 51.11, 63.64,
66.67, 59.09, 13.33, 74.42, 2.33, 0, 4.44, 2.27, 2.44, 8.89,
2.22, 4.55, 4.44, 9.09, 4.44, 2.33)), row.names = c(NA, -48L), .Names = c("dimension",
"area", "label", "variable", "value"), class = "data.frame")
Following the advice from another thread, I then calculate the locations of the labels, and create the labels themselves
library(plyr)
library(ggplot2)
data = ddply(data, .(label), transform, pos = (cumsum(value) - 0.5 * value))
data$pos[data$pos<5]<-4
data$x_label = paste0(sprintf("%.0f", data$value), "%")
Then I create the plot
heat_plot <- ggplot(data, aes(x = label, y = value, fill = variable))+
geom_bar(stat = "identity",position="fill")+
scale_fill_manual(values= c(SD="dark red",D="firebrick3",A="chartreuse3",SA="dark green") ) +
coord_flip()+
scale_y_continuous(labels=c(0,25,50,75,100))+
guides(fill=FALSE)+
theme(axis.title.x = element_blank())+
theme(axis.title.y = element_blank())+
geom_text(aes(y = pos/100, label = x_label))
heat_plot
This produces the following plot, which looks good, though I am worried about overlapping labels. As you can see, the first two labels on the fourth column from the top are already getting close. Any ideas for nicely separating all labels? Is there an automated process?