How to define color of intersection in a Venn diagram?
r, venn-diagram
Solution
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 `str`ucture 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)
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)
I'm quite sure you could work directly on the `grobs` using clipping functions in `grid` or `gridSVG` package.
Problem
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) ``` 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) ``` 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) ``` 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: 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.