I am plotting a series of Likert scale questions as stacked bar charts. They need to be labelled but some of the segments are two small and get overlaps like the example below (with sample code below it). Is there a clever way to either only label sections that are big enough to fit the label or a way to stagger how the labels are presented?
q1a<-rep(c("A", "B", "C", "D"), c(2, 5,45,45))
q1b<-rep(c("A", "B", "C", "D"), c(45,45,2, 5))
data<-data.frame(q1a,q1b)
data %>%
select(q1a:q1b) %>%
pivot_longer(cols = everything(), names_to = "Question") %>%
filter(!is.na(value)) %>%
count(Question, value) %>%
group_by(Question) %>%
mutate(Pct = n / sum(n)) %>%
ggplot(aes(fill = value, x = Pct, y = fct_rev(Question)))
geom_bar(position = "fill", stat = "identity")
geom_text(aes(label = paste0(sprintf("%1.0f", Pct * 100), "%")), position = position_stack(vjust = 0.5), size = 3)
scale_fill_brewer(palette = "Blues")
theme_bw()
scale_x_continuous(labels = scales::percent)
labs(title = "Question 1", y = "Question", x = "Percentage")
theme(legend.title = element_blank())
CodePudding user response:
If I were you, I'll only display labels for Pct
greater than 5% using if_else()
in geom_text(aes())
. If it's less than 5%, display nothing.
Also, since your geom_bar
position is fill
, you should also use position = position_fill()
in geom_text
to align the position.
library(tidyverse)
data %>%
select(q1a:q1b) %>%
pivot_longer(cols = everything(), names_to = "Question") %>%
filter(!is.na(value)) %>%
dplyr::count(Question, value) %>%
group_by(Question) %>%
mutate(Pct = n / sum(n)) %>%
ggplot(aes(fill = value, x = Pct, y = fct_rev(Question)))
geom_bar(position = "fill", stat = "identity")
geom_text(aes(label = if_else(Pct > 0.05, paste0(sprintf("%1.0f", Pct * 100), "%"), NULL)),
position = position_fill(vjust = 0.5), size = 3)
scale_fill_brewer(palette = "Blues")
theme_bw()
scale_x_continuous(labels = scales::percent)
labs(title = "Question 1", y = "Question", x = "Percentage")
theme(legend.title = element_blank())