Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define color of intersection in a Venn diagram?

Tags:

r

venn-diagram

I found many resources on how to draw Venn diagrams in R. Stack Overflow has a lot of them. However, I still can't draw my diagrams the way I want. Take the following code as an example:

library("VennDiagram")

A <- 1:4
B <- 3:6
d <- list(A, B)

vp <- venn.diagram(d, fill = c("white", "white"), alpha = 1, filename = NULL, 
  category.names=c("A", "B"))
grid.draw(vp)

enter image description here

I want the intersection between the sets to be red. However, if I change any of the white colors to red, I get the following:

vp_red <- venn.diagram(d, fill = c("red", "white"), alpha = 1, filename = NULL, 
  category.names=c("A", "B"))
grid.draw(vp_red)

enter image description here

That's not quite what I want. I want only the intersection to be red. If I change the alpha, this is what I get:

vp_alpha <- venn.diagram(d, fill = c("red", "white"), alpha = 0.5, filename = NULL, 
  category.names=c("A", "B"))
grid.draw(vp_alpha)

enter image description here

Now I have pink in my intersection. This is not what I want as well. What I want is something like this image from Wikipedia:

enter image description here

How can I do this? Maybe VennDiagram package can't do it and I need some other package, but I've been testing different ways to do it, and I'm not being able to find a solution.

like image 617
Marcus Nunes Avatar asked May 14 '17 11:05

Marcus Nunes


People also ask

How do you illustrate an intersection in a Venn diagram?

Sets are represented in a Venn diagram by circles drawn inside a rectangle representing the universal set. The region outside the circle represents the complement of the set. The overlapping region of two circles represents the intersection of the two sets. Two circles together represent the union of the two sets.

What is a ∩ B in Venn diagram?

In making a Venn diagram, we are often interested in the intersection of two sets—that is, what items are shared between categories. In this diagram, the teal area (where blue and green overlap) represents the intersection of A and B, or A ∩ B.


2 Answers

I will show two different possibilities. In the first example, polyclip::polyclip is used to get the intersection. In the second example, circles are converted to sp::SpatialPolygons and we get the intersection using rgeos::gIntersection. Then we re-plot the circles and fill the intersecting area.


The resulting object when using venn.diagram is

"of class gList containing the grid objects that make up the diagram"

Thus, in both cases we can grab relevant data from "vp". First, check the structure and list the grobs of the object:

str(vp)
grid.ls()
# GRID.polygon.234
# GRID.polygon.235
# GRID.polygon.236 <~~ these are the empty circles
# GRID.polygon.237 <~~ $ col : chr "black"; $ fill: chr "transparent"
# GRID.text.238 <~~ labels
# GRID.text.239
# GRID.text.240
# GRID.text.241
# GRID.text.242 

1. polyclip

Grab x- and y-values, and put them in the format required for polyclip:

A <- list(list(x = as.vector(vp[[3]][[1]]), y = as.vector(vp[[3]][[2]])))
B <- list(list(x = as.vector(vp[[4]][[1]]), y = as.vector(vp[[4]][[2]])))

Find intersection:

library(polyclip)
AintB <- polyclip(A, B)

Grab labels:

ix <- sapply(vp, function(x) grepl("text", x$name, fixed = TRUE))
labs <- do.call(rbind.data.frame, lapply(vp[ix], `[`, c("x", "y", "label")))

Plot it!

plot(c(0, 1), c(0, 1), type = "n", axes = FALSE, xlab = "", ylab = "")
polygon(A[[1]])
polygon(B[[1]])
polygon(AintB[[1]], col = "red")
text(x = labs$x, y = labs$y, labels = labs$label)

enter image description here


2. SpatialPolygons and gIntersection

Grab the coordinates of the circles:

# grab x- and y-values from first circle
x1 <- vp[[3]][["x"]]
y1 <- vp[[3]][["y"]]

# grab x- and y-values from second circle
x2 <- vp[[4]][["x"]]
y2 <- vp[[4]][["y"]]

Convert points to SpatialPolygons and find their intersection:

library(sp)
library(rgeos)
p1 <- SpatialPolygons(list(Polygons(list(Polygon(cbind(x1, y1))), ID = 1))) 
p2 <- SpatialPolygons(list(Polygons(list(Polygon(cbind(x2, y2))), ID = 2))) 

ip <- gIntersection(p1, p2) 

Plot it!

# plot circles 
plot(p1, xlim = range(c(x1, x2)), ylim = range(c(y1, y2))) 
plot(p2, add = TRUE) 

# plot intersection
plot(ip, add = TRUE, col = "red") 

# add labels (see above)
text(x = labs$x, y = labs$y, labels = labs$label)

enter image description here


I'm quite sure you could work directly on the grobs using clipping functions in grid or gridSVG package.

like image 166
Henrik Avatar answered Sep 21 '22 02:09

Henrik


It's very easy in eulerr R package

library(eulerr)
plot(euler(c("A"=5,"B"=4,"A&B"=2)),quantities = TRUE,fills=c("white","white","red"))

euler set colours

like image 33
djneuron Avatar answered Sep 19 '22 02:09

djneuron