在 ggplot 中用气泡注释绘图

Mr.*_*ver 3 graphics r graph ggplot2

我正在尝试从 highcharts复制此折线图。注释包含在语音/文本气泡中。我尝试在 ggplot 中使用 geom_label 执行此操作。为了获取点,我添加了具有向上或向下填充三角形形状的 geom_point 。虽然这适用于深色和不透明的填充和颜色,但它不适用于带有黑色轮廓的白色半透明填充,因为您可以清楚地看到三角形的底部。

有人知道解决这个问题的方法或更好的方法吗?

代码:

library(ggplot)

ggplot(france, aes(Distance, Elevation))+
  geom_area(fill = "#90ed7d", color = "#434348", 
            size = 0.7, alpha = 0.5)+ # area chart
  # location labels
  geom_label(aes(x, y-200, label = text), data = plot_labels[-3,],
             label.padding = unit(.4, "lines"), label.size = unit(.4, "mm"),
             label.r = unit(.05, "lines"), alpha = 0.5,
             vjust = 0.5, size = 3, family = "Lucida Grande")+ 
  # location labels points
  geom_point(aes(x, y-105, fill = "white"), data = plot_labels[-3,], 
             shape = 24, fill = "#FFFFFF80", size = 3, color = "black")+
  # elevation labels
  geom_label(aes(x, y+200, label = text), data = text_labels[-3,],
             label.padding = unit(.4, "lines"), label.size = unit(.4, "mm"),
             label.r = unit(.05, "lines"), color = "#404040",
             fill = "#404040",
             vjust = 0.5, size = 3, family = "Lucida Grande")+
  # text in white color for elevation labels 
  geom_text(aes(x, y+200, label = text), data = text_labels,
            vjust = 0.5, size = 3, family = "Lucida Grande", 
            colour = "#ffffff")+
  # elevation labels points
  geom_point(aes(x, y+105), data = text_labels[-3,], 
             shape = 25, fill = "#404040", size = 3, color = "#404040")+
  scale_y_continuous(labels = function (x) paste(x, "m"),
                     limits = c(0, 1600),
                     expand = c(0,0),
                     breaks = seq(0, 1500, 500))+
  scale_x_continuous(labels = function(x) paste(x, "km"),
                     expand = c(0,1.5), breaks = seq(0, 200, 25),
                     limits = c(0, max(france$Distance)))+
  ggtitle("2017 Tour de France Stage 8: Dole - Station des Rousses")+
  theme_minimal()+
  theme(panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.ticks.x = element_line("#d6d7e6"),
        axis.ticks.length.x = unit(.25, "cm"),
        text = element_text("Lucida Grande", size = 11))
Run Code Online (Sandbox Code Playgroud)

数据:

france <- read.csv(file = "https://raw.githubusercontent.com/mrRlover/data/main/Stackoverflow/tour_de_france_stage_8.csv")

plot_labels <- read.csv("https://raw.githubusercontent.com/mrRlover/data/main/Stackoverflow/labels.csv")

text_labels <- read.csv("https://raw.githubusercontent.com/mrRlover/data/main/Stackoverflow/text_labels.csv", encoding = "UTF-8", sep = ",")

colnames(france) <- c("Distance", "Elevation")

colnames(plot_labels) <- gsub("point__", "", colnames(plot_labels))

colnames(text_labels) <- gsub("point__", "", colnames(text_labels))

text_labels$text <- gsub("<br>", "\n", text_labels$text)
Run Code Online (Sandbox Code Playgroud)

目标图: 在此输入图像描述

电流输出:

在此输入图像描述

Jon*_*ing 5

这是一种半手动方法,它采用specifications包含标签信息的表格,并将每个坐标转换为一系列 8 个点,从而定义气泡的轮廓。然后可以将它们放入geom_poly以吸引气泡。

在此输入图像描述

虚假数据:

set.seed(42)
fake_data <- data.frame(x = 1:100,
                        y = cumsum(rnorm(100, 0.1)))
Run Code Online (Sandbox Code Playgroud)

定义标签:

library(tidyverse)
tri_width = 3
tri_height = 1
specifications <- data.frame(
  id = ids,
  x = c(12, 47, 94),
  y = c(11, 1, 17),
  y_dir = c(1, -1, 1),
  label = c("label 1", "label 2 is very wide", "label 3\nhas a\nfew lines"),
  width = c(15, 40, 19),
  height = c(3, 3, 7)
)
Run Code Online (Sandbox Code Playgroud)

将每个标签行转换为 8 行,定义每个气泡的轮廓:

bubbles <- specifications %>%
  uncount(8, .id = "pos") %>%   # bubble will have 7 coords, last one repeated
  mutate(x = x + recode(pos, 
                    0,
                    tri_width/2,
                    width/2,
                    width/2,
                    -width/2,
                    -width/2,
                    -tri_width/2,
                    0),
         y = y + y_dir * recode(pos,
                    0,
                    tri_height,
                    tri_height,
                    tri_height + height,
                    tri_height + height,
                    tri_height,
                    tri_height,
                    0)
         )
Run Code Online (Sandbox Code Playgroud)

阴谋:

ggplot(fake_data, aes(x, y)) +
  geom_line() +
  geom_polygon(data = bubbles, 
               aes(x, y, group = id),
               fill = "white", color = "gray70", alpha = 0.85) +
  geom_text(data = specifications, 
            aes(label = label, y = y + y_dir*(tri_height + height/2)))
Run Code Online (Sandbox Code Playgroud)