slowkow / ggrepel

:round_pushpin: Repel overlapping text labels away from each other in your ggplot2 figures.
https://ggrepel.slowkow.com
GNU General Public License v3.0
1.21k stars 95 forks source link

Line labels to the right of plot without overlapping #185

Open ericpgreen opened 3 years ago

ericpgreen commented 3 years ago

I posted a replication attempt to SO that a user named Nicolás Velásquez solved with this answer.

3hL0N

aanWt

He describes his approach of drawing two geom_text_repel()s as a "lazy but consistent trick". I think it's actually pretty creative.

That said, I'm wondering if there is a more straightforward approach to solving this problem with ggrepel. Or if not, if this use case could be the basis for a feature request.

library(tidyverse)
library(ggrepel)
keep <- c("Israel", "United Arab Emirates", "United Kingdom",
          "United States", "Chile", "European Union", "China",
          "Russia", "Brazil", "World", "Mexico", "Indonesia",
          "Bangladesh")

owid <- read_csv("https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.csv") %>%
  filter(location %in% keep) %>%
  filter(date >= "2021-01-01" & date <= "2021-02-12") %>%
  select(location, date, total_vaccinations_per_hundred) %>%
  arrange(location, date) %>%
  group_by(location) %>%
  complete(date = seq.Date(as.Date("2021-01-01"), 
                           as.Date("2021-02-12"), 
                           by="day")) %>%
  fill(total_vaccinations_per_hundred) %>%
  ungroup() %>%
  mutate(location = factor(location),
         location = fct_reorder2(location, total_vaccinations_per_hundred,
                                 total_vaccinations_per_hundred)) %>%
  mutate(label = if_else(date == max(date), 
                         as.character(location), 
                         NA_character_))

G01 <-  
  owid %>%
  ggplot(aes(x=date, y=total_vaccinations_per_hundred, group=location,
             color=location)) +
  geom_point() + 
  geom_line() +
  scale_y_continuous(breaks=c(seq(0, 70, 10))) +
  scale_x_date(limits = as.Date(c("2021-01-01", "2021-02-25"))) +
  theme_minimal() + 
  labs(title = "Cumulative COVID-19 vaccination doses administered per 100 people",
       subtitle = "This is counted as a single dose, and may not equal the total number of people vaccinated, depending on the specific dose regime (e.g. people receive multiple doses).",
       caption = "Source: Official data collected by Our World in Data — Last updated 13 February, 11:40 (London time)",
       y="",
       x="") +
  theme(panel.grid.major.x = element_blank(),
        panel.grid.major.y = element_line(linetype = "dashed"),
        panel.grid.minor.y = element_blank(),
        panel.grid.minor.x = element_blank(),
        plot.title.position = "plot",
        plot.title = element_text(face="bold"),
        legend.position = "none") +
scale_x_date(breaks = as.Date(c("2021-01-01",
                                "2021-01-10",
                                "2021-01-15",
                                "2021-01-20",
                                "2021-01-25",
                                "2021-01-30",
                                "2021-02-04",
                                "2021-02-12")),
             labels = scales::date_format("%b %d"),
             limits = as.Date(c("2021-01-01",
                                "2021-03-01")))

G01 +
  geom_text_repel(aes(label = gsub("^.*$", " ", label)), # This will force the correct position of the link's right end.
                  segment.curvature = -0.1,
                  segment.square = TRUE,
                  segment.color = 'grey',
                  box.padding = 0.1,
                  point.padding = 0.6,
                  nudge_x = 0.15,
                  nudge_y = 1,
                  force = 0.5,
                  hjust = 0,
                  direction="y",
                  na.rm = TRUE, 
                  xlim = as.Date(c("2021-02-16", "2021-03-01")),
                  ylim = c(0,73.75)
  ) +
  geom_text_repel(data = . %>% filter(!is.na(label)),
                  aes(label = paste0("  ", label)),
                  segment.alpha = 0, ## This will 'hide' the link
                  segment.curvature = -0.1,
                  segment.square = TRUE,
                  # segment.color = 'grey',
                  box.padding = 0.1,
                  point.padding = 0.6,
                  nudge_x = 0.15,
                  nudge_y = 1,
                  force = 0.5,
                  hjust = 0,
                  direction="y",
                  na.rm = TRUE, 
                  xlim = as.Date(c("2021-02-16", "2021-03-01")),
                  ylim = c(0,73.75))
slowkow commented 3 years ago

Thanks for sharing!

Is the data available? If not, you might consider sharing a reprex.

ericpgreen commented 3 years ago

Sorry! I did not copy that part of the reprex by mistake.