解析维恩 table 以在 R 中创建维恩图

Parsing venn table to create Venn Diagram in R

我有 table 维恩图的值,我试图将其读入 R 并解析以便使用 VennDiagram 包进行绘图。我的 table 看起来像这样:

H3K27AC.bed H3K4ME3.bed gencode.bed Total   Name
        X   19184   gencode.bed
    X       6843    H3K4ME3.bed
    X   X   3942    H3K4ME3.bed|gencode.bed
X           5097    H3K27AC.bed
X       X   1262    H3K27AC.bed|gencode.bed
X   X       4208    H3K27AC.bed|H3K4ME3.bed
X   X   X   9222    H3K27AC.bed|H3K4ME3.bed|gencode.bed

我可以像这样读取 table 作为数据框:

> venn_table_df<-read.table(venn_table_file,header = TRUE,sep = "\t",stringsAsFactors = FALSE)
> venn_table_df
  H3K27AC.bed H3K4ME3.bed gencode.bed Total                                Name
1                                   X 19184                         gencode.bed
2                       X              6843                         H3K4ME3.bed
3                       X           X  3942             H3K4ME3.bed|gencode.bed
4           X                          5097                         H3K27AC.bed
5           X                       X  1262             H3K27AC.bed|gencode.bed
6           X           X              4208             H3K27AC.bed|H3K4ME3.bed
7           X           X           X  9222 H3K27AC.bed|H3K4ME3.bed|gencode.bed

我可以像这样从 table 中获取维恩图的类别

> venn_categories<-colnames(venn_table_df)[!colnames(venn_table_df) %in% c("Total","Name")] 
> venn_categories
[1] "H3K27AC.bed" "H3K4ME3.bed" "gencode.bed"

我什至可以做一个更容易阅读的总结table,像这样:

> venn_summary<-venn_table_df[!colnames(venn_table_df) %in% venn_categories]
> venn_summary
  Total                                Name
1 19184                         gencode.bed
2  6843                         H3K4ME3.bed
3  3942             H3K4ME3.bed|gencode.bed
4  5097                         H3K27AC.bed
5  1262             H3K27AC.bed|gencode.bed
6  4208             H3K27AC.bed|H3K4ME3.bed
7  9222 H3K27AC.bed|H3K4ME3.bed|gencode.bed

但令我难过的是如何从 table 中获取值并将它们正确分配给维恩图的区域。作为参考,三重维恩函数如下所示:

n1<-5097
n2<-6843
n3<-19184

n12<-4208
n13<-1262
n23<-3942

n123<-9222

venn <-draw.triple.venn(area1=n1+n12+n13+n123,
                        area2=n2+n23+n12+n123,
                        area3=n3+n23+n13+n123,
                        n12=n12+n123,
                        n13=n13+n123,
                        n23=n23+n123,
                        n123=n123,
                        category=venn_categories,
                        fill=c('red','blue','green'),
                        alpha=c(rep(0.3,3)))

但显然这需要手动设置值,这是不可取的,因为我有很多这样的数据集,并且还需要将其扩展到 4 向和 5 向 Venn's。我怎样才能让 R 找到维恩中每个字段的正确值?我尝试了多种不同的方法,使用 grepgrepl,并为与绘图每个区域的类别匹配的行设置数据帧的子集,但这没有正常工作。有什么建议么?顺便说一句,这个数据是从 HOMER 软件包的 mergePeaks 程序输出的。

我想我明白了,使用正则表达式在 table 中搜索情节的正确条目。这是完整的工作流程:

# load packages
library('VennDiagram')
library('gridExtra')

# read in the venn text
venn_table_df<-read.table(venn_table_file,header = TRUE,sep = "\t",stringsAsFactors = FALSE)
venn_table_df

看起来像这样:

> venn_table_df
  H3K27AC.bed H3K4ME3.bed gencode.bed Total                                Name
1                                   X 19184                         gencode.bed
2                       X              6843                         H3K4ME3.bed
3                       X           X  3942             H3K4ME3.bed|gencode.bed
4           X                          5097                         H3K27AC.bed
5           X                       X  1262             H3K27AC.bed|gencode.bed
6           X           X              4208             H3K27AC.bed|H3K4ME3.bed
7           X           X           X  9222 H3K27AC.bed|H3K4ME3.bed|gencode.bed

> # recreate it with this btw
> dput(venn_table_df)
structure(list(H3K27AC.bed = c("", "", "", "X", "X", "X", "X"
), H3K4ME3.bed = c("", "X", "X", "", "", "X", "X"), gencode.bed = c("X", 
"", "X", "", "X", "", "X"), Total = c(19184L, 6843L, 3942L, 5097L, 
1262L, 4208L, 9222L), Name = c("gencode.bed", "H3K4ME3.bed", 
"H3K4ME3.bed|gencode.bed", "H3K27AC.bed", "H3K27AC.bed|gencode.bed", 
"H3K27AC.bed|H3K4ME3.bed", "H3K27AC.bed|H3K4ME3.bed|gencode.bed"
)), .Names = c("H3K27AC.bed", "H3K4ME3.bed", "gencode.bed", "Total", 
"Name"), class = "data.frame", row.names = c(NA, -7L))

然后解析 table

# get the venn categories
venn_categories<-colnames(venn_table_df)[!colnames(venn_table_df) %in% c("Total","Name")] 


# make a summary table
venn_summary<-venn_table_df[!colnames(venn_table_df) %in% venn_categories]
venn_summary

# get the areas for the venn; add up all the overlaps that contain the given category 

# area1
area_n1<-sum(venn_summary[grep(pattern = paste0("(?=.*",venn_categories[1],")"),x = venn_summary$Name,perl = TRUE),][["Total"]])

# area2
area_n2<-sum(venn_summary[grep(pattern = paste0("(?=.*",venn_categories[2],")"),x = venn_summary$Name,perl = TRUE),][["Total"]])

# area3
area_n3<-sum(venn_summary[grep(pattern = paste0("(?=.*",venn_categories[3],")"),x = venn_summary$Name,perl = TRUE),][["Total"]])

# n12
area_n12<-sum(venn_summary[grep(pattern = paste0("(?=.*",venn_categories[1],")","(?=.*",venn_categories[2],")"),x = venn_summary$Name,perl = TRUE),][["Total"]])

# n13
area_n13<-sum(venn_summary[grep(pattern = paste0("(?=.*",venn_categories[1],")","(?=.*",venn_categories[3],")"),x = venn_summary$Name,perl = TRUE),][["Total"]])

# n23
area_n23<-sum(venn_summary[grep(pattern = paste0("(?=.*",venn_categories[2],")","(?=.*",venn_categories[3],")"),x = venn_summary$Name,perl = TRUE),][["Total"]])


# n123
area_n123<-sum(venn_summary[grep(pattern = paste0("(?=.*",venn_categories[1],")","(?=.*",venn_categories[2],")","(?=.*",venn_categories[3],")"),x = venn_summary$Name,perl = TRUE),][["Total"]])


venn <-draw.triple.venn(area1=area_n1,
                        area2=area_n2,
                        area3=area_n3,
                        n12=area_n12,
                        n13=area_n13,
                        n23=area_n23,
                        n123=area_n123,
                        category=venn_categories,
                        fill=c('red','blue','green'),
                        alpha=c(rep(0.3,3)))

关键是使用正则表达式仅获取包含维恩地区所有类别的 table 条目。这比我希望的要复杂一些,并且需要手动设置以适应四路和五路 venns,但到目前为止它仍然有效。我对其他可能能够简化流程并更容易扩大规模的建议持开放态度。

万一有人觉得这有用,现在有一个非常简单的过程可以将这些数字放入近似比例的维恩图中。使用 nVennR 包创建图表的方法之一是从头开始。如 vignette 中所述,每个区域的值均按特定顺序输入,这恰好与 table 中的相同。唯一不同的是,nVennR 期望在开始时多一个值,对应于外部区域(这个值应该是 0,但无论如何都会被忽略)。这使得程序非常简单:

> vt <- read.table('clipboard', header = T)
> vt
  H3K27AC.bed H3K4ME3.bed gencode.bed Total                                Name
1           0           0           X 19184                         gencode.bed
2           0           X           0  6843                         H3K4ME3.bed
3           0           X           X  3942             H3K4ME3.bed|gencode.bed
4           X           0           0  5097                         H3K27AC.bed
5           X           0           X  1262             H3K27AC.bed|gencode.bed
6           X           X           0  4208             H3K27AC.bed|H3K4ME3.bed
7           X           X           X  9222 H3K27AC.bed|H3K4ME3.bed|gencode.bed
> myV <- createVennObj(nSets = 3, sNames = c('H3K27Ac', 'H3K4ME3', 'gencode'), sSizes = c(0, vt$Total))
> vp <- plotVenn(nVennObj = myV)

结果: 此过程的另一个优点是它可以扩展到更多的组。