Diverging bar chart

Author

Saed Jama

library(tidyverse)
library(readxl)

data <- read_excel("data.xlsx")
#preparation
summary_data <- data |> 
  count(District, perception, name = "count") |> 
  group_by(District) |> 
  mutate(percent = round(count/sum(count)*100, 0)) |> 
  select(-count) # Removes the raw count column

# right
offset <- 28

right <- summary_data |> 
  filter(perception== "Neutral") |> 
  mutate(xmin = max(summary_data$percent) + offset,
         xmax = xmin + percent,
         x = (xmin + xmax) / 2)


summary_data |>
  filter(perception != "Neutral") |> 
  pivot_wider(names_from = perception,
              values_from = percent) |> 
  mutate(Disagree = -Disagree,
         `Strongly disagree` = -`Strongly disagree`) |> 
  pivot_longer(cols = c(`Strongly disagree`, Disagree, Agree, `Strongly agree`),
               names_to = "perception",
               values_to = "percent") |> 
  mutate(perception = factor(perception,
                             levels = c("Strongly disagree", "Disagree", "Strongly agree", "Agree", "Neutral"))) |> 
  ggplot(aes(x = percent,
             y = District,
             fill = perception)) +
  geom_col(width = 0.6) +
  
  geom_text(aes(label = paste0(abs(percent), "%")),
            size = 10, size.unit = "pt",
            position = position_stack(vjust = 0.5)) +
  geom_crossbar(data = right,
                mapping = aes(x = x,
                              xmin = xmin,
                              xmax = xmax,
                              y = District,
                              fill = "Neutral"),
                inherit.aes = FALSE,
                width = 0.6,
                color = NA) +
  
  geom_text(data = right,
            mapping = aes(x = xmin + 2,
                          y = District,
                          label = paste0(percent, "%")),
            inherit.aes = FALSE,
            size = 10, size.unit = "pt", hjust = 0) +
  
  geom_vline(xintercept = 0, color = "#c0c0c0") + 
  
  scale_fill_manual(
    name = NULL,
    breaks = c("Strongly disagree", "Disagree", "Agree", "Strongly agree", "Neutral"),
    values = c("Strongly disagree" = "#fa8072",
                               "Disagree" = "#ffaaa5",
                               "Agree" = "#79d0cc",
                              "Strongly agree"= "#20b2aa",
                              "Neutral" = "#c0c0c0")) +
  labs(title = "How communities perceive publish services",
       caption = "Source: BeinStatistics",
       x = NULL,
       y = NULL) +
  
  theme(
    plot.title = element_text(hjust = 0.5,
                              size = 11,
                              face = "bold",
                              margin = margin(b = 20, t = 10)),
    legend.position = "top",
    legend.text = element_text(face = "bold", size = 9),
    legend.key.size = unit(8, "pt"),
    legend.margin = margin(b = -3, r = 60),
    axis.text = element_text(colour = "black",
                             size = 10, 
                             hjust = 0),
    axis.text.x = element_blank(),
    axis.ticks = element_blank(),
    panel.background = element_blank(),
    plot.caption = element_text(face = "bold",
                                size = 10,
                                hjust = 0))