Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to avoid overlapping legends for multiple geom_point layers in ggplot2

I’m trying to create a chart with 2 geom_points and a geom_text_repel layer. When I display my legend, the geom_points overlap. The main data points should be represented as empty circles, while the "region"-specific points should be filled circles. Additionally, the points corresponding to regions are not displayed correctly in the legend.

enter image description here

library(ggplot2)
library(ggrepel)
library(stringr)

set.seed(123)
data_filtered <- data.frame(
    evolution = runif(15, -10, 10),
    tauxpourmille = runif(15, 0, 100),
    faits = sample(1:100, 15, replace = TRUE),
    Code.région = sample(letters[1:3], 15, replace = TRUE),
    Code.département = sample(LETTERS[1:5], 15, replace = TRUE)
)

evol_tpm_reg_filtered <- data.frame(
    evolution_reg = runif(3, -10, 10),
    tauxpourmille = runif(3, 0, 100),
    Code.région = letters[1:3]
)

x_label <- "Évolution"
y_label <- "Taux pour mille"

region_colors <- c("red", "blue", "green")

ggplot(data_filtered, aes(x = evolution, y = tauxpourmille, size = faits, color = factor(Code.région))) +
    geom_point(shape = 1, stroke = 1.3, alpha = 0.6, show.legend = TRUE) +
    geom_text_repel(aes(label = Code.département),
                    family = "sans",
                    box.padding = 3,
                    size = 5,
                    min.segment.length = 0,
                    force = 20,
                    max.overlaps = 50,
                    segment.size = 0.5,
                    show.legend = FALSE) +
    geom_point(data = evol_tpm_reg_filtered, aes(x = evolution_reg, y = tauxpourmille, color = factor(Code.région)),
               size = 5, shape = 16, show.legend = TRUE) +
    labs(x = str_wrap(x_label, width = 90),
         y = str_wrap(y_label, width = 35),
         color = "Region",
         size = "Faits") +
    theme_minimal() +
    scale_color_manual(values = region_colors) +
    scale_size_area(max_size = 30,
                    breaks = c(min(data_filtered$faits), median(data_filtered$faits), max(data_filtered$faits)),
                    labels = scales::number_format(accuracy = 1)) +
    theme(axis.title.x = element_text(family = "sans", margin = margin(t = 15)),
          axis.title.y = element_text(family = "sans", margin = margin(r = 15)),
          axis.text.x = element_text(face = "bold", family = "sans"),
          axis.text.y = element_text(face = "bold", family = "sans"),
          axis.line.x = element_line(size = 1, color = "lightgray"),
          axis.line.y = element_line(size = 1, color = "lightgray"),
          legend.position = "right") +
    expand_limits(x = range(data_filtered$evolution) + c(-0.5, 0.5) * diff(range(data_filtered$evolution)),
                  y = range(data_filtered$tauxpourmille) + c(-0.5, 0.5) * diff(range(data_filtered$tauxpourmille)))

How can I make sure that the geom_point of “Faits” is an empty circle?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Simply drop show.legend=TRUE from your geom_points:

library(ggplot2)
library(ggrepel)
library(stringr)

set.seed(123)
data_filtered <- data.frame(
  evolution = runif(15, -10, 10),
  tauxpourmille = runif(15, 0, 100),
  faits = sample(1:100, 15, replace = TRUE),
  Code.région = sample(letters[1:3], 15, replace = TRUE),
  Code.département = sample(LETTERS[1:5], 15, replace = TRUE)
)

evol_tpm_reg_filtered <- data.frame(
  evolution_reg = runif(3, -10, 10),
  tauxpourmille = runif(3, 0, 100),
  Code.région = letters[1:3]
)

x_label <- "Évolution"
y_label <- "Taux pour mille"

region_colors <- c("red", "blue", "green")

ggplot(data_filtered, aes(
  x = evolution, y = tauxpourmille,
  size = faits, color = factor(Code.région)
)) +
  geom_point(shape = 1, stroke = 1.3, alpha = 0.6) +
  geom_text_repel(
    aes(label = Code.département),
    family = "sans",
    box.padding = 3,
    size = 5,
    min.segment.length = 0,
    force = 20,
    max.overlaps = 50,
    segment.size = 0.5,
    show.legend = FALSE
  ) +
  geom_point(
    data = evol_tpm_reg_filtered,
    aes(x = evolution_reg),
    size = 5, shape = 16
  ) +
  labs(
    x = str_wrap(x_label, width = 90),
    y = str_wrap(y_label, width = 35),
    color = "Region",
    size = "Faits"
  ) +
  theme_minimal() +
  scale_color_manual(values = region_colors) +
  scale_size_area(
    max_size = 30,
    breaks = c(
      min(data_filtered$faits),
      median(data_filtered$faits),
      max(data_filtered$faits)
    ),
    labels = scales::number_format(accuracy = 1)
  ) +
  theme(
    axis.title.x = element_text(family = "sans", margin = margin(t = 15)),
    axis.title.y = element_text(family = "sans", margin = margin(r = 15)),
    axis.text.x = element_text(face = "bold", family = "sans"),
    axis.text.y = element_text(face = "bold", family = "sans"),
    axis.line.x = element_line(linewidth = 1, color = "lightgray"),
    axis.line.y = element_line(linewidth = 1, color = "lightgray"),
    legend.position = "right"
  ) +
  expand_limits(
    x = range(data_filtered$evolution) + c(-0.5, 0.5) * diff(range(data_filtered$evolution)),
    y = range(data_filtered$tauxpourmille) + c(-0.5, 0.5) * diff(range(data_filtered$tauxpourmille))
  )

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading