来自聚类和共同因子列表的维恩图

时间:2011-11-14 13:06:25

标签: r combinations data-visualization factor-analysis

我有一个包含~50000个聚类列表的输入文件,并且每个聚类中都有多个因子(总共约1000万个条目),请参阅下面的一个小例子:

set.seed(1)
x = paste("cluster-",sample(c(1:100),500,replace=TRUE),sep="")
y = c(
  paste("factor-",sample(c(letters[1:3]),300, replace=TRUE),sep=""),
  paste("factor-",sample(c(letters[1]),100, replace=TRUE),sep=""),
  paste("factor-",sample(c(letters[2]),50, replace=TRUE),sep=""),
  paste("factor-",sample(c(letters[3]),50, replace=TRUE),sep="")
)
data = data.frame(cluster=x,factor=y)

在另一个问题的帮助下,我得到了一个像这样的因素同时出现的饼图:

counts = with(data, table(tapply(factor, cluster, function(x) paste(as.character(sort(unique(x))), collapse='+'))))
pie(counts[counts>1])

但是现在我想得到一个因子共现的维恩图。理想情况下,也可以采用每个因子的最小计数阈值。例如,不同因素的维恩图,以便每个群中的每一个都必须在每个群集中存在n> 10。

我试图找到一种用聚合生成表计数的方法,但无法使其工作。

1 个答案:

答案 0 :(得分:21)

我提供了两个解决方案,使用两个具有维恩图功能的不同包。如您所料,两者都涉及使用aggregate()函数的初始步骤。

我倾向于选择venneuler包的结果。它的默认标签位置并不理想,但您可以通过查看相关的plot方法(可能使用locator()来选择坐标)来调整它们。

解决第一个问题:

一种可能性是使用venneuler()包中的venneuler来绘制维恩图。

library(venneuler)

## Modify the "factor" column, by renaming it and converting
## it to a character vector.
levels(data$factor) <- c("a", "b", "c")
data$factor <- as.character(data$factor)

## FUN is an anonymous function that determines which letters are present
## 2 or more times in the cluster and then pastes them together into 
## strings of a form that venneuler() expects.
##
inter <- aggregate(factor ~ cluster, data=data,
                   FUN = function(X) {
                       tab <- table(X)
                       names <- names(tab[tab>=2])
                       paste(sort(names), collapse="&")
                   })            
## Count how many clusters contain each combination of letters
counts <- table(inter$factor)
counts <- counts[names(counts)!=""]  # To remove groups with <2 of any letter
#  a   a&b a&b&c   a&c     b   b&c     c 
# 19    13    12    14    13     9    12 

## Convert to proportions for venneuler()
ps <- counts/sum(counts)

## Calculate the Venn diagram
vd <- venneuler(c(a=ps[["a"]], b = ps[["b"]], c = ps[["c"]],
                  "a&b" = ps[["a&b"]],
                  "a&c" = ps[["a&c"]],
                  "b&c" = ps[["b&c"]],
                  "a&b&c" = ps[["a&b&c"]]))
## Plot it!
plot(vd)

关于我在编写此代码时所做选择的一些注意事项:

  • 我已将因子的名称从"factor-a"更改为"a"。你显然可以改变它。

  • 我只需要在每个群集中计算每个因子> = 2倍(而不是> 10)。 (那是用这个小数据子集来演示代码。)

  • 如果您查看中间对象counts,您会看到它包含一个未命名的初始元素。该元素是包含少于2个字母的聚类数。您可以更好地决定是否要在计算后续ps('比例')对象时包含这些内容。

enter image description here

解决第二个问题:

另一种可能性是在Bioconductor包vennCounts()中使用vennDiagram()limma。要下载软件包,follow the instructions here.与上面的venneuler解决方案不同,结果图中的重叠与实际交叉度不成比例。相反,它用实际频率注释图表。 (请注意,此解决方案不涉及对data$factor列的任何修改。)

library(limma)

out <- aggregate(factor ~ cluster, data=data, FUN=table)
out <- cbind(out[1], data.frame(out[2][[1]]))

counts <- vennCounts(out[, -1] >= 2)
vennDiagram(counts, names = c("Factor A", "Factor B", "Factor C"),
            cex = 1, counts.col = "red")

enter image description here