How to define color of intersection in a Venn diagram?

风流意气都作罢 提交于 2019-12-01 07:14:03

问题


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.


回答1:


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)


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.



来源:https://stackoverflow.com/questions/43963293/how-to-define-color-of-intersection-in-a-venn-diagram

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!