alex
alex

Reputation: 21

How to match legend bubble sizes in a bubble piechart map in R

When using bubble piecharts to map counts of 3 categories in different sites across a map, I cannot find a solution for indicating accurately each (bubble) piechart size in the legend.

pacman::p_load(ggplot2, dplyr, tidyr, sf, rnaturalearth, rnaturalearthdata, scatterpie)
#my summarised data
coropango_summary <- data.frame(site = c("KOU","LMB","MMG","MND","MRG","MSS","NDO","OYN","PTK","TRQ"),
                                lat = c(1.80,0.41,0.34,1.34,1.53,0.47,0.11,1.36,-0.59,-3.03),
                                long = c(12.29,10.13,12.52,13.12,11.56,11.34,10.45,11.34,12.49,11.29),
                                Bos = c(2,45,1,1,1,0,1,2,0,1),
                                Gnu = c(2,1,0,1,0,1,0,0,0,1),
                                undet = c(0,0,0,0,0,0,1,0,1,0),
                                host_sum = c(4,46,1,2,1,1,2,2,1,2)
)
#get map of Gabon and its neighbours
central_africa_map <- ne_countries(scale = "medium", continent = "Africa", returnclass = "sf")
gabon_map <- subset(central_africa_map, admin == "Gabon")
neighboring_countries <- subset(central_africa_map, admin != "Gabon" & sovereignt %in% c("Equatorial Guinea", "Cameroon", "Republic of the Congo"))
gabon_regions <- ne_states(country = "Gabon", returnclass = "sf")
ocean_color <- "steelblue1"
host_counts <- unique(sort(coropango_summary$host_sum))

gabon <- ggplot(data = gabon_map) +
  geom_sf(fill = "white", color = "black") +
  geom_sf(data = neighboring_countries, fill = "grey95", color = "black", linetype = "solid") +
  geom_sf(data = gabon_map, fill = "white", color = "black", linewidth = .5) +
  geom_sf(data = gabon_regions, fill = NA, color = "darkgrey", linetype = "dotted", linewidth = .4) +
  geom_scatterpie(data = coropango_summary, aes(x = long, y = lat, group = site,
                                                r = sqrt(host_sum)/10, size = host_sum),
                  cols = c("Bos","Gnu", "undet"),
                  color = NA, alpha = 0.6) +
  geom_scatterpie_legend(radius = sqrt(coropango_summary$host_sum)/10,
                         x = 8, y = -2.95, n = 4, labeller = function(value) host_counts) +
  scale_fill_manual(values = c("Bos" = "goldenrod2","Gnu" = "darkgreen","undet" = "firebrick4")) +
  geom_hline(yintercept = 0, color = "black", linewidth = 0.2, linetype = "solid") +
  annotate("text", x = 12.2, y = 2.7, label = "Cameroon", size = 4, fontface = "bold") +
  annotate("text", x = 10.6, y = 1.62, label = "Equatorial\nGuinea", size = 4, fontface = "bold") +
  annotate("text", x = 13.5, y = -3.1, label = "Republic of the\nCongo", size = 4, fontface = "bold") +
  labs(fill = "Host") +
  theme_minimal() +
  coord_sf(xlim = c(7, 15), ylim = c(-4, 3), expand = FALSE) +
  theme(
    panel.background = element_rect(fill = ocean_color, color = NA),
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    axis.text.y = element_text(),
    panel.grid = element_blank()
  ) +
  scale_y_continuous(breaks = c(0))

The results is a map where the minimum and maximum bubbles seem to be of the right size, but not the intermediates (sizes 2 and 4) which are much larger then the corresponding scatterpies. Matching these bubbles to the scatterpies on the map is the main issue. Here is what I managed so far [Result](https://i.sstatic.net/cwFPJWfg.png)

Secondly, the mapping of `host_sum` appears in legend and I have no idea how to remove it. I think that the circle areas should be matched somewhere, but I cannot figure out how and where. Any help is greatly appreciated. I have tried mapping each size (1,2,4,46) as separate `geom_scatterpie` but could not control the sizes of untransformed values.

Also, I have tried [creating the legend separately](Create a concentric circle legend for a ggplot bubble chart), but it did not turn out well, likely due to my limited understanding of R.

Upvotes: 2

Views: 41

Answers (1)

stefan
stefan

Reputation: 125697

To match the radiuses in the scatterpie legend with the scatterpies use the breaks= argument instead of radius=. The "issue" is that under the hood geom_scatterpie_legend will choose nice breaks using scales::breaks_extended based on the vector of values passed to radius=. Fro your second issue, drop size = host_sum from geom_scatterpie:

library(ggplot2)
library(scatterpie)

ggplot(data = gabon_map) +
  geom_sf(fill = "white", color = "black") +
  geom_sf(data = neighboring_countries, fill = "grey95", color = "black", linetype = "solid") +
  geom_sf(data = gabon_map, fill = "white", color = "black", linewidth = .5) +
  geom_sf(data = gabon_regions, fill = NA, color = "darkgrey", linetype = "dotted", linewidth = .4) +
  geom_scatterpie(
    data = coropango_summary, aes(
      x = long, y = lat, group = site,
      r = sqrt(host_sum) / 10
    ),
    cols = c("Bos", "Gnu", "undet"),
    color = NA, alpha = 0.6
  ) +
  geom_scatterpie_legend(
    breaks = sqrt(host_counts) / 10,
    x = 8, y = -2.95, n = 4,
    labeller = function(value) host_counts
  ) +
  scale_fill_manual(values = c("Bos" = "goldenrod2", "Gnu" = "darkgreen", "undet" = "firebrick4")) +
  geom_hline(yintercept = 0, color = "black", linewidth = 0.2, linetype = "solid") +
  annotate("text", x = 12.2, y = 2.7, label = "Cameroon", size = 4, fontface = "bold") +
  annotate("text", x = 10.6, y = 1.62, label = "Equatorial\nGuinea", size = 4, fontface = "bold") +
  annotate("text", x = 13.5, y = -3.1, label = "Republic of the\nCongo", size = 4, fontface = "bold") +
  labs(fill = "Host") +
  theme_minimal() +
  coord_sf(xlim = c(7, 15), ylim = c(-4, 3), expand = FALSE) +
  theme(
    panel.background = element_rect(fill = ocean_color, color = NA),
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    axis.text.y = element_text(),
    panel.grid = element_blank()
  ) +
  scale_y_continuous(breaks = c(0))

enter image description here

Upvotes: 2

Related Questions