Making a labelled slope plot with the help of R's ggrepel and ggplot2 (CC313)
Pat uses ggplot2 and ggrepel to generate a labelled slope plot based on a similar plot showing survey sentiments for two groups of people. He customizes the appearance using pivot_longer, group_by, mutate, slice_max, geom_line, geom_vline, annotate, geom_text_repel, scale_x_discrete, scale_color_gradient2, coord_cartesian, labs, and theme. The newsletter describing how I would go about generating the figure can be found here.
Code
library(tidyverse)
library(ggrepel)
library(ggtext)
set.seed(19760620)
survey <- tibble(
value = c("Happiness", "Cleanliness", "Peace and quiet", "Landscape",
"Speed of life", "Biodiversity", "Recreation", "Aesthetics",
"Cultural value", "Historical value", "Cost of living",
"Population density", "Openness", "Tourism", "Smells",
"Commerce", "Education", "Farm stands", "Bicycling",
"Walkability"),
clean = c(seq(1, 30, length = 18), 40, 50),
farmer = abs(clean + runif(20, min = -5, max = 5)),
non_farmer = abs(clean + runif(20, min = -5, max = 5))) %>%
select(-clean) %>%
pivot_longer(cols = c(farmer, non_farmer),
names_to = "population", values_to = "rate") %>%
mutate(population = factor(population,
levels = c("non_farmer", "farmer"))) %>%
group_by(value) %>%
mutate(diff = rate[1] - rate[2])
subset <- survey %>%
group_by(value) %>%
slice_max(rate)
subset_farmer <- subset %>%
filter(population == "farmer")
subset_non_farmer <- subset %>%
filter(population == "non_farmer")
survey %>%
ggplot(aes(x = population, y = rate, group = value, label = value,
color = diff)) +
geom_line(show.legend = FALSE) +
geom_vline(xintercept = 0.85) +
annotate("text", x = 0.78, y = c(0, 20, 40, 60),
label = c("0%", "20%", "40%", "60%"), size = 3.5) +
annotate("text", x = 0.84, y = 63, label = "Favorability", hjust = 1) +
geom_text_repel(data = subset_farmer, direction = "y",
nudge_x = 0.5, hjust = 1, size = 3, segment.color = "gray",
color = "black") +
geom_text_repel(data = subset_non_farmer, direction = "y",
nudge_x = -0.75, hjust = 0, size = 3, segment.color = "gray",
color = "black") +
scale_x_discrete(breaks = c("non_farmer", "farmer"),
labels = c("Non-farmer", "Farmer")) +
scale_color_gradient2(low = "blue", high = "red", mid = "gray") +
coord_cartesian(clip = 'off', ylim = c(0, 60)) +
labs(x = NULL,
y = "Percent favorability",
title = "The main difference in favorability between farmers and non-farmers is there opinion of bicycling and walkability") +
theme_classic() +
theme(
plot.title = element_textbox_simple(face = "bold", size = 20, margin = margin(b = 10)),
axis.ticks = element_blank(),
axis.line = element_blank(),
axis.title = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(face = "bold")
)
ggsave("slope_plot.png", width = 6, height = 5)