2011-11-14 68 views
12

我有一個輸入文件,其中包含約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個才能被考慮。

我試圖找到一種方法來產生聚合的表計數,但無法使其工作。

+2

你看任何R包文氏圖?參見G. Jay Kerns使用'venneuler'庫的[最近的例子](http://stats.stackexchange.com/questions/16802/derive-pc-ab-from-coxs-two-rules/18209#18209)或者使用'venn'庫([Murdoch,2004](http://www.jstatsoft.org/v11/c01))的Stat軟件雜誌中的這篇簡短文章。如果這純粹是關於R編程,它應該遷移到SO。 –

+1

Avilella,這個問題可能不會得到任何答案,因爲它的主題略微偏離。你可能在SO上做得更好,它有一個活躍的R用戶社區。但請不要交叉發帖:如果您想遷移,請將標題提交給主持人注意。 – whuber

+0

我標記了它,但我看不到它被移到SO了... – 719016

回答

20

我提供了兩個解決方案,使用兩個不同的包與維恩圖功能。如您所料,兩者都涉及使用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

解決方案中的第二:

另一種可能性是採用vennCounts()vennDiagram()在Bioconductor的包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