ggtree — 基于 ggplot2 的 R 进化树可视化包
一句话说明
ggtree 是 Bioconductor 上的 R 包,用 ggplot2 的图层语法来画进化树——先画树骨架,再一层一层叠加热图、点图、文字注释等,和画普通 ggplot2 图一样直觉。白话理解:进化树的"ggplot2版本",叠图层就行。
安装与配置
# 安装 Bioconductor 管理器(首次)
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
# 安装 ggtree 及常用配套包
BiocManager::install(c(
"ggtree", # 核心包,进化树可视化
"treeio", # 读取各种树格式(IQ-TREE/BEAST/MrBayes输出)
"ggtreeExtra", # 在树外圈添加热图/条形图等面板
"ggplot2", # 图形语法基础
"ggstar" # 各种星形/特殊形状节点
))
# 确认安装版本
packageVersion("ggtree") # 当前稳定版 ≥ 3.10(Bioc 3.18)
核心用法
读树并画基础树
library(ggtree) # 加载 ggtree
library(treeio) # 加载 treeio(读各种格式)
# 读 Newick 格式树
tree <- read.tree("my_tree.nwk") # 读取 Newick 文件
# 读 IQ-TREE 输出(含 bootstrap 支持值)
tree <- read.iqtree("my_tree.treefile") # 读 IQ-TREE 结果文件
# 画最简单的矩形进化树
ggtree(tree) +
geom_tiplab(size = 3) # 在叶节点旁边显示名称,字号3
常用树型
# 矩形树(默认)
p1 <- ggtree(tree, layout = "rectangular")
# 圆形/辐射树(微生物多样性常用)
p2 <- ggtree(tree, layout = "circular")
# 扇形树(去掉根的圆形)
p3 <- ggtree(tree, layout = "fan", open.angle = 30) # 开口角度30度
# 无根树
p4 <- ggtree(tree, layout = "unrooted")
参数详解
| 函数 | 作用 | 常用参数 |
|---|
ggtree() | 画树骨架 | layout, color, size, linetype |
geom_tiplab() | 叶节点标签 | size, color, offset, align |
geom_tippoint() | 叶节点点 | aes(color=xxx), size |
geom_nodelab() | 内部节点标签(支持值) | aes(label=bootstrap) |
geom_hilight() | 高亮某个分支 | node, fill, alpha |
geom_cladelab() | 在分支外加弧形标注 | node, label, color |
gheatmap() | 在树旁边加热图 | data, width, offset |
facet_plot() | 在树旁边加条形图/点图等 | data, geom, mapping |
实战案例
案例1:给分支着色 + 添加支持值
library(ggtree)
library(ggplot2)
tree <- read.iqtree("bacteria.treefile") # 读 IQ-TREE 输出
ggtree(tree, aes(color = SH_alrt > 80)) + # 按 SH-aLRT 支持值着色分支
scale_color_manual(
values = c("TRUE" = "black", "FALSE" = "gray70"), # 高支持=黑,低支持=灰
name = "SH-aLRT > 80" # 图例名称
) +
geom_nodelab( # 显示节点支持值
aes(label = ifelse(SH_alrt > 80, SH_alrt, "")), # 只显示高支持值
size = 2, hjust = -0.1 # 字号2,稍微右移
) +
geom_tiplab(size = 2, offset = 0.01) + # 叶标签,字号2
theme_tree2() # 加上刻度轴
案例2:进化树 + 物种丰度热图(宏基因组常用)
library(ggtree)
library(ggtreeExtra)
library(ggplot2)
# 准备数据
tree <- read.tree("otu_tree.nwk") # 读 OTU 树
# OTU 丰度数据框:行为 OTU,列为样本
abund_df <- read.csv("otu_abund.csv", # 读丰度矩阵
row.names = 1)
# 画树
p <- ggtree(tree, layout = "circular", # 圆形布局
size = 0.3) + # 分支线宽
geom_tiplab(size = 1.5, offset = 0.5) # 叶名
# 在圆形树外圈叠加热图
p + geom_fruit(
data = abund_df, # 丰度数据
geom = geom_tile, # 用瓦片图呈现
mapping = aes(y = rownames(abund_df), # y轴对应叶节点名
x = variable, # x轴为样本名
fill = value), # 颜色=丰度值
offset = 0.08, # 离树的距离
pwidth = 0.5 # 热图宽度占比
) +
scale_fill_viridis_c(name = "Abundance") # 用 viridis 配色
案例3:高亮特定门的分支
# 找到某个分支的节点编号(MRCA = 最近公共祖先)
mrca_node <- MRCA(tree, c("OTU001", "OTU012")) # 找 OTU001 和 OTU012 的共同祖先
ggtree(tree) +
geom_hilight( # 高亮分支
node = mrca_node, # 指定节点
fill = "#2ca02c", # 高亮颜色:绿色
alpha = 0.3 # 透明度
) +
geom_cladelab( # 在分支外添加弧形标签
node = mrca_node,
label = "Firmicutes", # 标签文字
color = "#2ca02c", # 标签颜色
offset = 0.5, # 标签离树的距离
fontsize = 4 # 字号
) +
geom_tiplab(size = 2)
常见报错与解决
| 报错 | 原因 | 解决方法 |
|---|
Error in match.arg(layout) | layout 参数拼写错误 | 检查:rectangular/circular/fan/unrooted |
| 热图叶名不对齐 | 丰度矩阵行名与树叶名不一致 | intersect() 检查共同节点名 |
| 节点编号不对 | 内部节点从 N+1 开始(N=叶数) | ggtree(tree) + geom_text(aes(label=node)) 查看编号 |
gheatmap() 图例重叠 | 多个连续变量共用图例 | guides(fill = "none") 关闭某层图例 |
| 输出图片文字缺失 | ggplot2 PDF 中文字体问题 | cairo_pdf() 或 showtext 包 |
速查表
# 安装
BiocManager::install("ggtree")
# 读树(treeio)
read.tree() # Newick
read.nexus() # Nexus
read.iqtree() # IQ-TREE(含支持值)
read.beast() # BEAST 贝叶斯
# 常用 layout
"rectangular" "circular" "fan" "unrooted" "daylight" "equal_angle"
# 查节点编号
ggtree(tree) + geom_text(aes(label = node), size = 2)
# 保存图片
ggsave("tree.pdf", width = 12, height = 10) # 保存为 PDF
ggsave("tree.png", dpi = 300, width = 12, height = 10) # 保存为 PNG