Last active
January 9, 2025 14:45
-
-
Save lnalborczyk/3e965284deaa99291a63d7fcf2f8078f to your computer and use it in GitHub Desktop.
Generating Venn diagrams from % of variance via ggVennDiagram
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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