say.ff
say.ff

Reputation: 395

set the color of categories in venn diagram in r

I am using ggVennDiagram to creat a venn diagram. I would like to set the color of categories manually. Here is what I am trying, however the color of border line of the circles is not changed.

x <- list(A=1:5,B=2:7,C=3:6,D=4:9)
ggVennDiagram(x, label = "count", label_alpha = 0, 
          color =  c("A" = "yellow","B" ="steelblue",'C' = 'red', 'D' = 'black') ,
          set_color = c("A" = "yellow","B" ="steelblue", 'C' = 'red', 'D' = 'black')) +
 scale_fill_gradient(low = "#F4FAFE", high = "#4981BF")

Any Idea how I can match the colors of circle lines with the name of categories?

Thanks

Upvotes: 0

Views: 6213

Answers (2)

Marco Sandri
Marco Sandri

Reputation: 24262

The ggVennDiagram command calls the ggVennDiagram::plot_venn function for plotting colored areas. You can modify this function according to your needs.
See below my suggestion.

plot_venn <- function (x, show_intersect, set_color, set_size, label, label_geom, 
    label_alpha, label_color, label_size, label_percent_digit, 
    label_txtWidth, edge_lty, edge_size, ...)  {
    venn <- Venn(x)
    data <- process_data(venn)
    p <- ggplot() + geom_sf(aes_string(fill = "count"), data = data@region) + 
        geom_sf(aes_string(color = "name"), data = data@setEdge, 
            show.legend = F, lty = edge_lty, size = edge_size, color = set_color) + 
        geom_sf_text(aes_string(label = "name"), data = data@setLabel, 
            size = set_size, color = set_color) + theme_void()
    if (label != "none" & show_intersect == FALSE) {
        region_label <- data@region %>% dplyr::filter(.data$component == 
            "region") %>% dplyr::mutate(percent = paste(round(.data$count * 
            100/sum(.data$count), digits = label_percent_digit), 
            "%", sep = "")) %>% dplyr::mutate(both = paste(.data$count, 
            paste0("(", .data$percent, ")"), sep = "\n"))
        if (label_geom == "label") {
            p <- p + geom_sf_label(aes_string(label = label), 
                data = region_label, alpha = label_alpha, color = label_color, 
                size = label_size, lineheight = 0.85, label.size = NA)
        }
        if (label_geom == "text") {
            p <- p + geom_sf_text(aes_string(label = label), 
                data = region_label, alpha = label_alpha, color = label_color, 
                size = label_size, lineheight = 0.85)
        }
    }
    if (show_intersect == TRUE) {
        items <- data@region %>% dplyr::rowwise() %>% dplyr::mutate(text = stringr::str_wrap(paste0(.data$item, 
            collapse = " "), width = label_txtWidth)) %>% sf::st_as_sf()
        label_coord = sf::st_centroid(items$geometry) %>% sf::st_coordinates()
        p <- ggplot(items) + geom_sf(aes_string(fill = "count")) + 
            geom_sf_text(aes_string(label = "name"), data = data@setLabel, 
                inherit.aes = F) + geom_text(aes_string(label = "count", 
            text = "text"), x = label_coord[, 1], y = label_coord[, 
            2], show.legend = FALSE) + theme_void()
        ax <- list(showline = FALSE)
        p <- plotly::ggplotly(p, tooltip = c("text")) %>% plotly::layout(xaxis = ax, 
            yaxis = ax)
    }
    p
}

Then, you can run the code:

library(ggVennDiagram)
library(ggplot2)

# Replace the plot_venn function with the modified version
assignInNamespace(x="plot_venn", value=plot_venn, ns="ggVennDiagram")  

x <- list(A=1:5,B=2:7,C=3:6,D=4:9)
ggVennDiagram(x, label = "count", label_alpha = 0, 
          color =  c("A" = "yellow","B" ="steelblue",'C' = 'red', 'bdiv_human' = 'black') ,
          set_color = c("A" = "yellow","B" ="steelblue", 'C' = 'red', 'bdiv_human' = 'black')) +
 scale_fill_gradient(low = "#F4FAFE", high = "#4981BF") +
 scale_color_gradient(low = "#F4FAFE", high = "#4981BF")

enter image description here

Upvotes: 1

Peter
Peter

Reputation: 12699

From ggVennDiagram documentation it looks as if you have to build up the venn diagram rather than use the ggVennDiagram function. Maybe this adaptation from the documentation example gives you enough to work on...

Updated to include OP's comment for percentage count.

library(ggplot2)
library(ggVennDiagram)

x <- list(A=1:5,B=2:7,C=3:6,D=4:9)

venn <- Venn(x)
data <- process_data(venn)
ggplot() +
  # 1. region count layer
  geom_sf(aes(fill = count), data = venn_region(data)) +
  # 2. set edge layer
  geom_sf(aes(color = name), data = venn_setedge(data), show.legend = TRUE, size = 2) +
  # 3. set label layer
  geom_sf_text(aes(label = name), data = venn_setlabel(data)) +
  # 4. region label layer
  geom_sf_label(aes(label = paste0(count, " (", scales::percent(count/sum(count), accuracy = 2), ")")), 
                data = venn_region(data),
                size = 3) +
  scale_fill_gradient(low = "#F4FAFE", high = "#4981BF")+
  scale_color_manual(values = c("A" = "yellow","B" ="steelblue",'C' = 'red', 'D' = 'black'),
                     labels = c('D' = 'D = bdiv_human'))+
  theme_void()

Created on 2021-12-04 by the reprex package (v2.0.1)

Upvotes: 2

Related Questions