Skip to content

Instantly share code, notes, and snippets.

@lnalborczyk
Last active January 9, 2025 14:45
Show Gist options
  • Select an option

  • Save lnalborczyk/3e965284deaa99291a63d7fcf2f8078f to your computer and use it in GitHub Desktop.

Select an option

Save lnalborczyk/3e965284deaa99291a63d7fcf2f8078f to your computer and use it in GitHub Desktop.
Generating Venn diagrams from % of variance via ggVennDiagram
library(ggVennDiagram)
library(RColorBrewer)
library(tidyverse)
library(glue)
venn_3d <- function (
total_variance = 100, # total number of items
unique_x1 = 0.3, # 30% unique to X1
unique_x2 = 0.3, # 30% unique to X2
unique_y = 0.3, # 30% unique to Y
shared_x1_x2 = 0.05, # % shared between X1 and X2
shared_x1_y = 0.05, # % shared between X1 and Y
shared_x2_y = 0.05, # % shared between X2 and Y
shared_all = 0.1 # 10% shared across X1, X2, and Y
){
# computing the number of elements for each component
n_unique_x1 <- total_variance * unique_x1
n_unique_x2 <- total_variance * unique_x2
n_unique_y <- total_variance * unique_y
n_shared_x1_x2 <- round(total_variance * shared_x1_x2)
n_shared_x1_y <- round(total_variance * shared_x1_y)
n_shared_x2_y <- round(total_variance * shared_x2_y)
n_shared_all <- round(total_variance * shared_all)
# generating numbers for each component
x1_unique_numbers <- seq(1, n_unique_x1)
x2_unique_numbers <- seq(max(x1_unique_numbers) + 1, max(x1_unique_numbers) + n_unique_x2)
y_unique_numbers <- seq(max(x2_unique_numbers) + 1, max(x2_unique_numbers) + n_unique_y)
shared_x1_x2_numbers <- seq(max(y_unique_numbers) + 1, max(y_unique_numbers) + n_shared_x1_x2)
shared_x1_y_numbers <- seq(max(shared_x1_x2_numbers) + 1, max(shared_x1_x2_numbers) + n_shared_x1_y)
shared_x2_y_numbers <- seq(max(shared_x1_y_numbers) + 1, max(shared_x1_y_numbers) + n_shared_x2_y)
shared_all_numbers <- seq(max(shared_x2_y_numbers) + 1, max(shared_x2_y_numbers) + n_shared_all)
# combining into lists for x1, x2, and y
x <- list(
Y = c(y_unique_numbers, shared_x1_y_numbers, shared_x2_y_numbers, shared_all_numbers),
X1 = c(x1_unique_numbers, shared_x1_x2_numbers, shared_x1_y_numbers, shared_all_numbers),
X2 = c(x2_unique_numbers, shared_x1_x2_numbers, shared_x2_y_numbers, shared_all_numbers)
)
# 3D Venn diagram
# ggVennDiagram(
# x,
# label = "none",
# edge_size = 0.5,
# show_intersect = FALSE
# ) +
# theme(legend.position = "none") +
# scale_fill_distiller(palette = fill_palette) +
# # adding custom labels for subsets
# annotate(
# geom = "text", x = 2, y = 1.5,
# label = glue("a: {format(round(shared_x1_y, 2), nsmall = 2)}"),
# size = 4, color = "white"
# ) +
# annotate(
# geom = "text", x = -0.25, y = -2.5,
# label = glue("b: {format(round(shared_x2_y, 2), nsmall = 2)}"),
# size = 4, color = "white") +
# annotate(
# geom = "text", x = 2, y = -1.5,
# label = glue("c: {format(round(shared_all, 2), nsmall = 2)}"),
# size = 4, color = "white") +
# annotate(
# geom = "text", x = -1.5, y = 1,
# label = glue("d: {format(round(unique_y, 2), nsmall = 2)}"),
# size = 4, color = "white")
# custom made Venn diagram
# see https://gaospecial.github.io/ggVennDiagram/articles/fully-customed.html
venn <- Venn(x)
data <- process_data(venn)
ggplot() +
geom_polygon(aes(X, Y, fill = as.factor(id), group = id), data = venn_regionedge(data) ) +
geom_path(
aes(x = X, y = Y, group = id),
data = venn_setedge(data),
show.legend = FALSE,
linewidth = 1
) +
geom_text(
aes(x = X, y = Y, label = name),
data = venn_setlabel(data),
size = 5
) +
# adding custom labels for subsets
annotate(
geom = "text", x = 2, y = 1.5,
label = glue("a: {format(round(shared_x1_y, 2), nsmall = 2)}"),
size = 5
) +
annotate(
geom = "text", x = -0.25, y = -2.6,
label = glue("b: {format(round(shared_x2_y, 2), nsmall = 2)}"),
size = 5
) +
annotate(
geom = "text", x = 2, y = -1.5,
label = glue("c: {format(round(shared_all, 2), nsmall = 2)}"),
size = 5
) +
annotate(
geom = "text", x = -1.5, y = 0.75,
label = glue("d: {format(round(unique_y, 2), nsmall = 2)}"),
size = 5
) +
scale_fill_brewer(palette = "Spectral") +
coord_equal() +
theme_void() +
theme(legend.position = "none")
}
venn_4d <- function (
total_variance = 100,
unique_x1 = 0.2,
unique_x2 = 0.2,
unique_x3 = 0.2,
unique_y = 0.2,
shared_x1_x2 = 0.05,
shared_x1_y = 0.05,
shared_x2_y = 0.05,
shared_x1_x3 = 0.05,
shared_x2_x3 = 0.05,
shared_x3_y = 0.05,
shared_all = 0.05,
labels = FALSE,
alpha = 1
) {
# increasing the number of colour in the "Spectral" palette
# https://stackoverflow.com/questions/34106898/extending-rcolorbrewer-to-support-more-colors
mycolors <- colorRampPalette(brewer.pal(11, "Spectral") )(15)
# computing the number of elements for each component
n_unique_x1 <- total_variance * unique_x1
n_unique_x2 <- total_variance * unique_x2
n_unique_x3 <- total_variance * unique_x3
n_unique_y <- total_variance * unique_y
n_shared_x1_x2 <- round(total_variance * shared_x1_x2)
n_shared_x1_y <- round(total_variance * shared_x1_y)
n_shared_x2_y <- round(total_variance * shared_x2_y)
n_shared_x1_x3 <- round(total_variance * shared_x1_x3)
n_shared_x2_x3 <- round(total_variance * shared_x2_x3)
n_shared_x3_y <- round(total_variance * shared_x3_y)
n_shared_all <- round(total_variance * shared_all)
# generating numbers for each component
x1_unique_numbers <- seq(1, n_unique_x1)
x2_unique_numbers <- seq(max(x1_unique_numbers) + 1, max(x1_unique_numbers) + n_unique_x2)
x3_unique_numbers <- seq(max(x2_unique_numbers) + 1, max(x2_unique_numbers) + n_unique_x3)
y_unique_numbers <- seq(max(x3_unique_numbers) + 1, max(x3_unique_numbers) + n_unique_y)
shared_x1_x2_numbers <- seq(max(y_unique_numbers) + 1, max(y_unique_numbers) + n_shared_x1_x2)
shared_x1_y_numbers <- seq(max(shared_x1_x2_numbers) + 1, max(shared_x1_x2_numbers) + n_shared_x1_y)
shared_x2_y_numbers <- seq(max(shared_x1_y_numbers) + 1, max(shared_x1_y_numbers) + n_shared_x2_y)
shared_x1_x3_numbers <- seq(max(shared_x2_y_numbers) + 1, max(shared_x2_y_numbers) + n_shared_x1_x3)
shared_x2_x3_numbers <- seq(max(shared_x1_x3_numbers) + 1, max(shared_x1_x3_numbers) + n_shared_x2_x3)
shared_x3_y_numbers <- seq(max(shared_x2_x3_numbers) + 1, max(shared_x2_x3_numbers) + n_shared_x3_y)
shared_all_numbers <- seq(max(shared_x3_y_numbers) + 1, max(shared_x3_y_numbers) + n_shared_all)
# combining into lists for Y, X1, X2, and X3
x <- list(
Y = c(y_unique_numbers, shared_x1_y_numbers, shared_x2_y_numbers, shared_x3_y_numbers, shared_all_numbers),
X1 = c(x1_unique_numbers, shared_x1_x2_numbers, shared_x1_y_numbers, shared_x1_x3_numbers, shared_all_numbers),
X2 = c(x2_unique_numbers, shared_x1_x2_numbers, shared_x2_y_numbers, shared_x2_x3_numbers, shared_all_numbers),
X3 = c(x3_unique_numbers, shared_x1_x3_numbers, shared_x2_x3_numbers, shared_x3_y_numbers, shared_all_numbers)
)
# creating the Venn diagram using ellipses
venn <- Venn(x)
data <- process_data(venn)
ggplot() +
geom_polygon(
aes(X, Y, fill = as.factor(id), group = id),
data = venn_regionedge(data), alpha = alpha
) +
geom_path(
aes(X, Y, group = id),
data = venn_setedge(data),
show.legend = FALSE,
linewidth = 1
) +
geom_text(
aes(x = X, y = Y, label = name),
data = venn_setlabel(data),
size = 5
) + {
if (labels) annotate(
geom = "text", x = 0.32, y = 0.675,
label = glue("a: {format(round(shared_x1_y, 2), nsmall = 2)}"),
size = 5
)
} + {
if (labels) annotate(
geom = "text", x = 0.32, y = 0.425,
label = glue("b: {format(round(shared_x2_y, 2), nsmall = 2)}"),
size = 5
)
} + {
if (labels) annotate(
geom = "text", x = 0.4, y = 0.575,
label = glue("d: {format(round(shared_x1_x2, 2), nsmall = 2)}"),
size = 5
) } + {
if (labels) annotate(
geom = "text", x = 0.2, y = 0.55,
label = glue("h: {format(round(unique_y, 2), nsmall = 2)}"),
size = 5
) } + {
if (labels) annotate(
geom = "text", x = 0.5, y = 0.48,
label = glue("g: {format(round(shared_all, 2), nsmall = 2)}"),
size = 5
) } + {
if (labels) annotate(
geom = "text", x = 0.425, y = 0.38,
label = glue("f: {format(round(shared_x2_x3, 2), nsmall = 2)}"),
size = 5
) } + {
if (labels) annotate(
geom = "text", x = 0.575, y = 0.38,
label = glue("e: {format(round(shared_x1_x3, 2), nsmall = 2)}"),
size = 5
) } + {
if (labels) annotate(
geom = "text", x = 0.5, y = 0.3,
label = glue("c: {format(round(shared_x3_y, 2), nsmall = 2)}"),
size = 5
) } +
scale_fill_manual(values = mycolors) +
coord_equal() +
theme_void() +
theme(legend.position = "none")
}
# generating the intro 4-variable Venn diagram
venn_4d()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment