Venn diagram은 각 그룹에 어떠한 공통적인 속성이 있는지를 한눈에 보여줍니다. R에서는 여러 가지 도구에 의해서 제공됩니다. 그렇다 보니 어떤 도구를 선택해야 할지 많은 고민이 있습니다.
제가 실제로 논문 작업을 하면서, 어떤 도구를 써야 이미지를 수정, 편집하기 쉬울지 하나하나 사용해 보았습니다. 이를 간단하게 소개해드립니다👽.
예제 데이터
저는 항상 QIIME2의 moving-picture tutorial에 나오는 데이터를 사용합니다. 아마 마이크로바이옴을 처음 배우시는 사람들이 접하는 데이터이기 때문입니다. 그러나 venn diagram에 사용되는 데이터 형식만 알면, 다른 데이터에서도 모두 사용 가능합니다.
먼저 Venn diagram에 들어가는 데이터 형식은 List입니다.
set.seed(20240418)
ASVs <- paste("ASV",1:100,sep="")
venn_df <- list(
Sample01 = sample(ASVs,50),
Sample02 = sample(ASVs,30),
Sample03 = sample(ASVs,20),
Sample04 = sample(ASVs,35),
Sample05 = sample(ASVs,15)
)
venn_df
즉, 어떤 데이터든 각 샘플이 가진 속성을 list형식으로 가지고 있으면 문제가 없습니다.
하지만 아마 많은 마이크로바이옴 데이터는 데이터는 아래처럼 table형식을 가지고 있을 겁니다.
그러므로, 위 table형식을 가지고 있는 phyloseq(biom 형식)에서부터 시작하겠습니다.
먼저, 생물학적 데이터를 담고 있는 phyloseq형식을 불러오겠습니다.
예제 파일을 아래 첨부파일에서 다운로드 가능합니다.
library(phyloseq)
library(dplyr)
ps <- readRDS("./ps.rds") # 분석이 수행되는 곳에 파일 이동 후 불러오기
위 데이터는 몸의 각 4 부위에서 미생물 유전체 분석을 수행하였습니다. 우리는 각 부위에 따른 공통된 미생물 (ASV)의 개수를 알아봅시다.
먼저 phyloseq 파일은 feature table과 sample data가 따로 나뉘어 있습니다. 이를 통합해주어야 합니다.
meta <- data.frame(sample_data(ps))
otu <- data.frame(otu_table(ps))
table <- merge(meta, t(otu), by = "row.names")
table
여기서 각 body site에 해당하는 ASV 이름을 추출해 봅시다.
gut<- table %>%
filter(body.site %in% "gut") %>% # body site가 gut인 데이터 중에
select(which(colSums(.[10:779]) > 0)) %>% # feature table이 column 10~779에 위치, 이 중 전체 합이 0 이상
colnames()
tongue <- table %>%
filter(body.site %in%"tongue") %>%
select(which(colSums(.[10:779]) > 0)) %>%
colnames()
left.p <- table %>%
filter(body.site %in% "left palm" ) %>%
select(which(colSums(.[10:779]) > 0)) %>%
colnames()
right.p <- table %>%
filter(body.site %in% "right palm") %>%
select(which(colSums(.[10:779]) > 0)) %>%
colnames()
이 데이터를 list로 합쳐줍니다.
venn_df = list(`gut` = gut,
`tongue` = tongue,
`left palm` = left.p,
`right palm` = right.p
)
venn_df
만약 phyloseq을 사용하지 않는다면, 아래 예제 데이터를 대신 사용해주세요!
set.seed(20240418)
ASVs <- paste("ASV",1:100,sep="")
venn_df <- list(
Sample01 = sample(ASVs,50),
Sample02 = sample(ASVs,30),
Sample03 = sample(ASVs,20),
Sample04 = sample(ASVs,35),
Sample05 = sample(ASVs,15)
)
venn_df
1. gplot
install.packages("gplots")
library(gplots)
venn1 <- gplots::venn(venn_df)
venn1
png("./venn2.png", width = 7, height = 7, units = "in", res = 300, type = "cairo", bg = "transparent")
gplots::venn(venn_df)
dev.off()
가장 기본적인 그림이 나옵니다. 이를 보면, 왼손과 오른손이 공유하는 ASV가 198개로 가장 많군요!
이 패키지의 장점은 아래와 같습니다.
venn1_attr <- attr(venn1, "intersections")
venn1_attr$`left palm:right palm` %>% head
# [1] "fc5b641a0b0408d99ddfb2a5ba64da59" "4980b85712efeef1fc4563a9a949fe2e" "e0472171de6fa02a1f58e392ad3d000e"
# [2] "3b74a95b189e134bb34c191b7693455d" "678424c0e69dd311d2b536cfd69a91a4" "b3406cb10b6d6882837eaacbaec3553e"
속성을 뽑아서 각 그룹마다 공유하는 feature를 바로바로 확인할 수 있습니다.
2. VennDiagram
VennDiagram 패키지의 장점은, 시각 자료를 세부적으로 설정할 수 있다는 점입니다.
아래 속성을 보시면, 저장 위치와 선, 벤다이어그램, 글자의 색과 크기 모두 설정이 가능합니다.
install.packages("VennDiagram")
library(VennDiagram)
VennDiagram::venn.diagram(
x = venn_df,
category.names = c("gut", "tongue", "left palm", "right palm"),
filename = './venn_diagram.png', main = "Venn Diagram",
output=F,
col=c("#440154ff", '#21908dff', '#fde725ff', "#E7298A"),
height = 9,
width = 11,
resolution = 500,
units = "in",
imagetype = "png",
fill = c("#440154ff", '#21908dff', '#fde725ff', "#E7298A"),
cex = 2,
fontfamily = "sans",
cat.cex = 1.5,
cat.default.pos = "outer",
cat.fontfamily = "sans",
cat.col = c("#440154ff", '#21908dff', '#fde725ff', "#E7298A")
)
3. ggvenn
먼저 ggplot을 사용한 venn diagram이라는 것에 장점이 있습니다. 그러나 가장 큰 단점은 최대 4그룹 간의 비교만 지원한다는 점입니다.
if (!require(devtools)) install.packages("devtools")
devtools::install_github("yanlinlin82/ggvenn")
library(ggvenn)
ggvenn(
venn_df,
fill_color = c("#0073C2FF", "#EFC000FF", "#868686FF", "#CD534CFF"),
stroke_size = 0.5, set_name_size = 4
)
ggsave("./venn4.png", width = 7, height = 7, dpi = 300,
device = png, type = "cairo", bg = "transparent")
4. ggVenDiagram
공통된 feature의 퍼센트와 frequency를 색으로 알려주니 시각적으로 더욱 도움이 되는 것 같습니다.
if (!require(devtools)) install.packages("devtools")
devtools::install_github("gaospecial/ggVennDiagram")
library(ggVennDiagram)
p <- ggVennDiagram(venn_df,
label_alpha = 0,
category.names = c("gut", "tongue", "left palm", "right palm"))+
scale_fill_gradient(low = "#F4FAFE", high = "#4981BF")
p
ggsave("./venn3.png", width = 7, height = 7, dpi = 300,
device = png, type = "cairo", bg = "transparent")
5. UpSetR
Venn diagram의 또 다른 형식인 upset plot은 비교군이 많을 때 사용합니다. 적어도 5군 이상에서 사용하면 좋습니다.
Upset plot을 위해 데이터를 조금 수정해 줍시다. 각 그룹별로 feature table을 모두 합하였습니다.
install.packages("UpSetR")
library(UpSetR)
table2 <- table[, c(3, 10:779)] %>% # body.site 열과 feature table만 추출
dplyr::group_by(body.site) %>% # body.site에 따라 feature값 합하기
dplyr::summarize_all(sum) %>%
tibble::column_to_rownames("body.site") %>% # rownames을 body.site로 설정
t() %>% # 전치행렬
data.frame()
table2
Venn diagram은 각 feature가 얼마나 풍부한지는 중요하지 않습니다. 있는지 없는지만 따져야 합니다.
# https://github.com/waldronlab/MicrobiomeWorkshop/blob/master/vignettes/MicrobiomeWorkshop.Rmd
table3 <- (table2>0) *1
0 값 이상이면 모두 1을 넣어줍시다.
p <- upset(data.frame(table3),
sets=colnames(data.frame(table3)),
sets.bar.color = "#56B4E9",
order.by = "freq",
empty.intersections = "on")
p
png("./venn6.png", width = 10, height = 7, units = "in", res = 300, type = "cairo", bg = "transparent")
p
dev.off()
공유 그룹은 선과 점으로 표시하며, 공유하는 feature의 개수는 bar plot으로 나타납니다. 이를 보면 가장 많은 feature를 공유하는 그룹은 역시 손바닥 사이인 것을 볼 수 있습니다. 또한 전체 부위에서는 총 6개의 ASV를 공유하고 있습니다.
조금 더 고급버전인 ComplexUpset 패키지를 이용하면, 더 다양한 시각자료를 추가할 수 있습니다.
개인적인 추천
저는 ggVennDiagram 패키지를 추천합니다. 이유는 ggplot 형식이기 때문입니다. 이는 officer과 사용 시, 더욱더 편리하게 그림을 수정할 수 있습니다.
library(officer)
library(rvg)
library(ggVennDiagram)
p <- ggVennDiagram(venn_df,
label_alpha = 0,
category.names = c("gut", "tongue", "left palm", "right palm"))+
scale_fill_gradient(low = "#F4FAFE", high = "#4981BF")
p
# 빈 pptx만들기
read_pptx() %>%
print(target = "./example.pptx")
read_pptx( "./example.pptx")
# 편집 가능한 이미지로 변환
editable_graph <- rvg::dml(ggobj = p)
# 그림 저장
read_pptx( "./example.pptx") %>%
add_slide("Title Slide","Office Theme") %>%
ph_with(editable_graph,
location = ph_location(left=0, top=0,width = 7, height = 7, bg="transparent")) %>%
print(target = "./example.pptx")
이렇게 pptx형식으로 저장된 그림에서 글씨체를 바꾸거나 크기를 세밀하게 조정할 수 있습니다.
참고