这是一个递归解决方案,用于查找维恩图中的所有交点。 sets 可以是一个列表,其中包含任意数量的集合以查找其交集。出于某种原因,您正在使用的包中的代码都是针对每个集合大小进行硬编码的,因此它不会扩展到任意交叉点。
## Build intersections, 'out' accumulates the result
intersects <- function(sets, out=NULL) {
if (length(sets) < 2) return ( out ) # return result
len <- seq(length(sets))
if (missing(out)) out <- list() # initialize accumulator
for (idx in split((inds <- combn(length(sets), 2)), col(inds))) { # 2-way combinations
ii <- len > idx[2] & !(len %in% idx) # indices to keep for next intersect
out[[(n <- paste(names(sets[idx]), collapse="."))]] <- intersect(sets[[idx[1]]], sets[[idx[2]]])
out <- intersects(append(out[n], sets[ii]), out=out)
}
out
}
该函数构建成对的交叉点。为了避免构建重复的解决方案,它只在索引大于连接的索引的集合上调用自己(代码中的ii)。结果是所有交叉点的列表。如果传递命名组件,则结果将按照约定“set1.set2”等命名。
结果
## Some sample data
set.seed(0)
sets <- setNames(lapply(1:3, function(.) sample(letters, 10)), letters[1:3])
## Manually check intersections
a.b <- intersect(sets[[1]], sets[[2]])
b.c <- intersect(sets[[2]], sets[[3]])
a.c <- intersect(sets[[1]], sets[[3]])
a.b.c <- intersect(a.b, sets[[3]])
## Compare
res <- intersects(sets)
all.equal(res[c("a.b","a.c","b.c","a.b.c")], list(a.b=a.b, a.c=a.c, b.c=b.c, a.b.c=a.b.c))
# TRUE
res
# $a.b
# [1] "g" "i" "n" "e" "r"
#
# $a.b.c
# [1] "g"
#
# $a.c
# [1] "x" "g"
#
# $b.c
# [1] "f" "g"
## Get the counts of intersections
lengths(res)
# a.b a.b.c a.c b.c
# 5 1 2 2
或者,用数字
intersects(list(a=1:10, b=c(1, 5, 10), c=9:20))
# $a.b
# [1] 1 5 10
# $a.b.c
# [1] 10
# $a.c
# [1] 9 10
# $b.c
# [1] 10