Объедините текст и изображение в geom_label_repel в ggplot

Я пытаюсь построить линейный график и пометить последнюю точку каждой серии комбинацией текста и изображения. Я обычно использую для этого пакет ggrepel, и у меня нет проблем с тем, чтобы сделать это только с текстом. Моя проблема в том, что я не могу понять, как добавить изображение на этикетку.

Я думал, что ярлык типа Country <img src='https://link.com/to/flag.png' width='20'/> подойдет, и вот что я пытался сделать:

library(dplyr)
library(ggplot2)
library(ggrepel)

# example df
df <- data.frame(
  Country = c(rep("France", 5), rep("United Kingdom", 5)),
  Ratio = rnorm(10),
  Days = c(seq(1, 5, 1), seq(4, 8, 1)),
  abbr = c(rep("FR", 5), rep("GB", 5))) %>% 
  group_by(Country) %>% 
  
  # add "label" only to last point of the graph
  mutate(label = if_else(Days == max(Days), 
                         # combine text and img of country's flag
                         true = paste0(Country, " <img src='https://raw.githubusercontent.com/behdad/region-flags/gh-pages/png/", abbr, ".png' width='20'/>"), 
                         false = NA_character_)
  )
  

# line graph
ggplot(data = df, aes(x = Days, y = Ratio, color = Country)) +
  geom_line(size = 1) +
  theme(legend.position = "none") +
  
  geom_label_repel(aes(label = label),
                   nudge_x = 1,
                   na.rm = T)

Но при этом получается необработанная этикетка, а не название страны с ее флагом, как задумано:

введите описание изображения здесь

Очевидно, это не выход, может ли кто-нибудь мне помочь?


person MonkeyBack    schedule 16.10.2020    source источник


Ответы (1)


Попробуйте этот подход, используя ggtext функцию geom_richtext(). При желании вы можете настроить другие элементы. Вот код:

library(dplyr)
library(ggplot2)
library(ggrepel)
library(ggtext)
# example df
df <- data.frame(
  Country = c(rep("France", 5), rep("United Kingdom", 5)),
  Ratio = rnorm(10),
  Days = c(seq(1, 5, 1), seq(4, 8, 1)),
  abbr = c(rep("FR", 5), rep("GB", 5))) %>% 
  group_by(Country) %>% 
  
  # add "label" only to last point of the graph
  mutate(label = if_else(Days == max(Days), 
                         # combine text and img of country's flag
                         true = paste0(Country, " <img src='https://raw.githubusercontent.com/behdad/region-flags/gh-pages/png/", abbr, ".png' width='20'/>"), 
                         false = NA_character_)
  )


# line graph
ggplot(data = df, aes(x = Days, y = Ratio, color = Country,label = label)) +
  geom_line(size = 1) +
  theme(legend.position = "none") +
  geom_richtext(na.rm = T,nudge_x = -0.1,nudge_y = -0.1)

Выход:

введите описание изображения здесь

person Duck    schedule 16.10.2020
comment
Спасибо @Duck, в этом примере это работает в принципе, однако в моем реальном наборе данных более двух серий, большинство из которых заканчиваются примерно одинаковыми значениями. Моя проблема сейчас в том, что метки больше не отталкивают друг друга и график нечитаем. - person MonkeyBack; 16.10.2020
comment
@MonkeyBack Попробуйте проверить аргументы ggrepel в функции из ggtext. Это должна быть опция, такая как checkoverlap=T, которая может лучше расположить надписи! - person Duck; 16.10.2020
comment
Я только что нашел это на ggrepel GitHub, так что, похоже, это еще невозможно с ggrepel . И я предполагаю, что, поскольку люди спрашивают о функциях ggtext в ggrepel, это должно быть потому, что ggrepel функции также недоступны в _6 _... - person MonkeyBack; 17.10.2020
comment
@MonkeyBack В этом случае я предлагаю выбрать несколько стран для построения графика или создать группы и использовать фасеты, чтобы их можно было разделить! - person Duck; 17.10.2020