rggplot2venn-diagram

Manual change the color of the circles using sf package in R


I would like to create a Venn Diagram with sf + ggplot2 packages.

How to manually change the colors of the circles and the intersection regions of the two inner circles? Changing the scale fill in {ggplot2} does not affect the colors of the circles

Initilisation

library(ggplot2)
library(dplyr)
library(sf)

create_circle_sf <- function(x, y, radius, label, fill_id) {
  st_point(c(x, y)) %>%
    st_buffer(radius) %>%
    st_sfc(crs = 4326) %>%
    st_sf(label = label, fill_id = fill_id, geometry = .)
}



# radii from n values
r1 <- sqrt(6000 / pi)
r2 <- sqrt(2000 / pi)
r3 <- sqrt(2000 / pi)


# Add a new `fill_id` for color mapping
circle1 <- create_circle_sf(0, 0, r1, "Party Representatives", "A")
circle2 <- create_circle_sf(14, 0, r2, "Unique parties", "B")
circle3 <- create_circle_sf(-13, 0, r3, "Client Companies", "C")

# Combine all
circles_all <- bind_rows(circle1, circle2, circle3)
# calculate intersection (e.g., between 1 & 2)
intersect12 <- st_intersection(circle1, circle2)
intersect13 <- st_intersection(circle1, circle3)
intersect23 <- st_intersection(circle2, circle3)
# combine all
circles_all <- bind_rows(circle1, circle2, circle3)

Plot attempt


# Define color manually for each fill_id
custom_colors <- c("A" = "#77bca2", "B" = "#FFEB3B", "C" = "#FF9800")
# Circle centers and labels
label_df <- data.frame(
  x = c(0, 14, -13),
  y = c(0, 0, 0),
  label = c("Party Representatives: 41",
            paste0("Unique\n Parties: ", 20),
            paste0("Unique\nClient\nCompanies: ", 30))
)

ggplot() +
  geom_sf(data = circles_all, aes(fill = fill_id), alpha = 0.8) +  
  # use fill_id here
  geom_sf(data = intersect12, fill = "white", alpha = 0.8) +
  geom_sf(data = intersect13, fill = "white", alpha = 0.8) +
  geom_sf(data = intersect23, fill = "white", alpha = 0.8) +
  geom_text(data = label_df, aes(x = x, y = y, label = label),
            size = 4.5, fontface = "bold", lineheight = 0.9) +
  scale_fill_manual(values = custom_colors) +
  theme_void() +
  coord_sf() +
  theme(legend.position = "none")

enter image description here


Solution

  • Two options, plot all circles, with alpha and custom fill colours, overlaps will get different fill because of alpha. Or plot the 1st circle, then overlaps, manually setting the colours without alpha, this way we can set the overlap colours manually.

    gg1 <- ggplot() +
      geom_sf(data = circles_all, aes(fill = fill_id), alpha = 0.3) +  
      scale_fill_manual(values = custom_colors, guide = "none") +
      labs(title = "1") + coord_sf() + theme_void()
    
    gg2 <- ggplot() +
      geom_sf(data = circle1, fill = "#77bca2") +  
      geom_sf(data = intersect12, fill = "#FFEB3B") +
      geom_sf(data = intersect13, fill = "#FF9800") +
      geom_sf(data = intersect23, fill = "red") +
      labs(title = "2") + coord_sf() + theme_void()
      
    library(patchwork)
    
    gg1|gg2
    

    enter image description here