5

I'm making a graph for different countries where I'm adding manually a text with geom_label_repel. I'm having problems changing the border color in that text (I want it in a different color from the text). Here is a reproducible example:


#Create dataframe 
countries <- c("Mundo", "Argentina", "Brasil", "Chile", "Colombia", "Mexico", "Perú", "Estados Unidos")
countries <- rep(countries, 120)
vaccinations <- data.frame(countries)
vaccinations$countries <- factor(vaccinations$countries , levels = c("Mundo", "Argentina", "Brasil", "Chile",
                                                          "Colombia", "Mexico", "Perú", "Estados Unidos"))
vaccinations <- vaccinations %>%
  group_by(countries) %>%
  mutate(month = 1:120,
         vaccines = runif(120, min = 0, max = 5))

#Write text to add manually in each country
saved_text <- data.frame(
  label_pais = c("10.10 per 100", "11.76 per 100", "12.58 per 100", "62.94 per 100", 
                 "5.98 per 100", "8.84 per 100", "3.18 per 100", "55.96 per 100"),
  countries  = c("Mundo", "Argentina", "Brasil", "Chile",
               "Colombia", "Mexico", "Perú", "Estados Unidos"))

saved_text$countries <- factor(saved_text$countries, levels = c("Mundo", "Argentina", "Brasil", "Chile",
                                                                    "Colombia", "Mexico", "Perú", "Estados Unidos"))

#Plot
ggplot()+
  geom_line(data = vaccinations, 
            aes(x = month, y = vaccines, colour = factor(countries)), size = 2, show.legend = FALSE) +
  facet_wrap( ~ countries, ncol = 4)+
  geom_label_repel(data = saved_text,
                   aes(y = 6, x = 1, label = label_pais)) #How can I change the border color?

I get this enter image description here I understand that the colour argument in geom_label_repel changes the color of the border (as well as the text color) but what I want is the text color to be, let' say, black and the border red. Does anybody knows how to achieve this? Thanks in advance!

Andres Gonzalez
  • 219
  • 1
  • 8

2 Answers2

2

This is a challenging problem. Mostly because the color is only defined in the grob once which applies both to the border and text itself.

Let's start by getting some colors:

ggplot() +
  geom_line(data = vaccinations, 
            aes(x = month, y = vaccines, colour = factor(countries)), size = 2, show.legend = FALSE) +
  facet_wrap( ~ countries, ncol = 4) +
  geom_label_repel(data = saved_text,
                   aes(y = 6, x = 1, label = label_pais, color = factor(countries))) 

enter image description here

This is totally a hack, but let's edit the code for the ggrepel package on the fly. I snooped around the source code until I found the function that creates the text.

First, we'll need to unload the package. Then use fixInNamespace to edit the plotting function:

unloadNamespace("ggrepel")
fixInNamespace("makeContent.labelrepeltree","ggrepel")

If you're using Rstudio, you'll get a pop-up editor. If you're using a console, you'll see something slightly different. On line 77, you'll find where the text attributes are defined.

enter image description here

Change row$colour to "black" and save the changes. You might get an error. Don't worry.

Now, repeat the same code after re-loading the package:

library(tidyverse)
library(ggrepel)
ggplot() +
  geom_line(data = vaccinations, 
            aes(x = month, y = vaccines, colour = factor(countries)), size = 2, show.legend = FALSE) +
  facet_wrap( ~ countries, ncol = 4) +
  geom_label_repel(data = saved_text,
                   aes(y = 6, x = 1, label = label_pais, color = factor(countries))) 

enter image description here

All of this will revert when you restart your R session.

Ian Campbell
  • 23,484
  • 14
  • 36
  • 57
2

Another workaround could be calling geom_label_repel twice, the second time with no border. Using your example:

library(ggplot2)
library(ggrepel)

ggplot()+
  geom_line(
    data = vaccinations, 
    aes(x = month, y = vaccines, colour = factor(countries)), 
    size = 2, 
    show.legend = FALSE
  ) +
  facet_wrap( ~ countries, ncol = 4) +
  geom_label_repel(
    data       = saved_text,
    mapping    = aes(y = 6, x = 1, label = label_pais, color = factor(countries)),
    label.size = 0.9,  
    seed       = 1234, # to get same positions as bellow
  ) + 
  geom_label_repel(
    data = saved_text,
    aes(y = 6, x = 1, label = label_pais),
    color      = "black", # desired color
    label.size = NA,      # No border
    seed       = 1234     # same positions as above
  )
el-grec0
  • 21
  • 3