ggtree–绘图1

ggtree
Author

大番薯本薯

Published

January 14, 2026

Modified

January 14, 2026

使用ggtree()函数等于使用ggplot(tree, aes(x, y)) + geom_tree() + theme_tree()

对于ggtree及其相关包中的许多函数,我将它们按照“点-线-面-域”的形式进行了分类:

首先让我们加载一个树,并添加额外的相关信息,用于后续函数的使用说明。

suppressMessages(library(treeio))
suppressMessages(library(ggtree))
# library(ggimage)

nwk <- system.file("extdata", "sample.nwk", package = "treeio")
tree <- treeio::read.tree(nwk)
tree$node.label <- c("root", paste("node", 2:treeio::Nnode(tree)))
p <- ggtree(tree)

点元素

点元素是ggtree树图中最重要的部分,因为每种点元素都有自己的坐标。使用fortify()函数提取绘图数据(见上一节),我们可以看到root就是x = 0的点,是一种特殊得nodeisTip用来区分是否是tip;x,y构成了node与tip的坐标;branchy构成了branch的坐标(此处坐标是branch的中心点);angle用来描述x极坐标化后的角度。

pd <- ggtree::fortify(tree)
pd
#> # A tbl_tree abstraction: 25 × 9
#> # which can be converted to treedata or phylo 
#> # via as.treedata or as.phylo
#>   parent  node branch.length label isTip     x     y branch angle
#>    <int> <int>         <dbl> <chr> <lgl> <dbl> <dbl>  <dbl> <dbl>
#> 1     20     1             4 A     TRUE     48    12   46    332.
#> 2     20     2             4 B     TRUE     48    13   46    360 
#> 3     19     3             5 C     TRUE     43    11   40.5  305.
#> 4     18     4             6 D     TRUE     36    10   33    277.
#> 5     17     5            21 E     TRUE     48     9   37.5  249.
#> 6     22     6             4 F     TRUE     48     7   46    194.
#> # ℹ 19 more rows

# root
dplyr::filter(pd, parent == node)
#> # A tibble: 1 × 9
#>   parent  node branch.length label isTip     x     y branch angle
#>    <int> <int>         <dbl> <chr> <lgl> <dbl> <dbl>  <dbl> <dbl>
#> 1     14    14             0 root  FALSE     0  3.46      0  95.8

让我们先简单地展示一下这些信息:

p +
  geom_nodelab(hjust = 0) +
  geom_text2(aes(subset = branch != 0, x = branch), label = "branch") +
  geom_tiplab()

root相关的函数

p +
  geom_rootpoint(shape = 21, size = 5, color = "red", fill = "blue") +
  geom_rootedge(rootedge = 2)

node相关的函数

node可以有具体的含义,例如共同祖先,也可以没有。相关的函数有:

p +
  geom_nodepoint(shape = 21, size = 5, color = "red", fill = "blue") +
  geom_nodelab(hjust = 0)

从图中也可以看到,root属于node,相关美学映射及label被调整。可以使用subset映射来剔除对root的调整:

p +
  geom_nodepoint(aes(subset = node != parent), shape = 21, size = 5, color = "red", fill = "blue") +
  geom_nodelab(aes(subset = node != parent), hjust = 0)

tip相关的函数

tip也称为taxa,是树末端的点。与之相关的函数有:

p +
  geom_tippoint(shape = 21, size = 5, color = "red", fill = "blue") +
  geom_tiplab()

geom_tiplab()label映射外,还有image映射,可以用来添加额外的图片或“phhylopic”。

annimals <- c("Homo sapiens", "Pan troglodytes", "Gorilla gorilla", "Pongo abelii", "Hylobates lar", "Macaca mulatta", "Papio anubis", "Lemur catta", "Mus musculus", "Rattus norvegicus", "Canis lupus", "Felis catus", "Gallus gallus")

d <- ggimage::phylopic_uid(annimals)
d$name <- tree$tip.label

ggtree(tree) %<+% d +
  geom_tiplab(aes(image = uid), color = "grey", geom = "phylopic", offset = 2.5) +
  hexpand(0.1)

geom_tiplab()也支持解析emoji字符,详见ggtree-chaper8

branch相关的函数

branch没有对应的函数,它作为树的主体,其映射由ggtree()geom_tree()直接进行调整,标签可以由geom_text()geom_label()进行设置:

p +
  geom_tree(aes(color = "red")) +
  geom_text(aes(x = branch, y), label = "branch")

其他相关函数

除上述函数外,ggtree提供了一些其他用来处理“点”元素的函数,它们大多具有普适性,大致可以分为两类:

ggtree特有

geom_range()

如果某个“点”元素具有某个范围信息,那么就可以使用geom_range()进行绘制,例如我们为tree添加枝长的范围,并使用scale_x_range()为其添加x轴(但轴的意义不大,具体可见ggtree-5.3):

rangeInfo <- tibble(
  label = c("node 2", "A"),
  year = list(c(3, 7), c(1, 2))
)

tree2 <- full_join(tree, rangeInfo, by = "label")

ggtree(tree2) +
  geom_tiplab() +
  geom_nodelab() +
  geom_range("year", color = "red", alpha = .6, size = 2) +
  scale_x_range() +
  theme_tree2()
#> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
#> ℹ Please use `linewidth` instead.
#> ℹ The deprecated feature was likely used in the ggtree package.
#>   Please report the issue at <https://github.com/YuLab-SMU/ggtree/issues>.

geom_inset()

geom_inset()接受一个ggplot对象list,且list的name是nodetip)的编号(即pd中的node列)。它会将这些对象绘制到nodetip)上或nodetip)对应的branch上。

ggtree提供了nodepie()nodebar()两个函数,分别绘制饼图和条形图,你可以创建任何ggplot对象,或者使用ggplotify包来将某个对象转换为ggplot对象。

df2 <- as.data.frame(abs(matrix(rnorm(39), ncol = 3)))
df2$node <- 1:13
bars <- nodebar(df2, cols = 1:3)
bars <- lapply(bars, function(g) g + scale_fill_discrete())
#> Error in `scale_fill_discrete()`:
#> ! could not find function "scale_fill_discrete"

p + geom_inset(bars, width = .08, height = .05, x = "node")

Warning

在实际运行中,nodepie()会报错,暂时不清楚原因

ggplot升级版

具有subset映射,可以直接根据subset映射`对绘图数据进行过滤,然后进行绘制:

p +
  geom_label2(aes(subset = isTip, label = label)) +
  geom_point2(aes(subset = !isTip), color = "red", size = 5)
#> Warning in geom_label2(aes(subset = isTip, label = label)): Ignoring unknown
#> parameters: `label.size`

这些函数不仅可以用于tree的绘制,其他类型的散点图也可以使用。除subset映射外,ggtree还提供了两个函数,可以直接应用到geom_*()函数中:

p +
  geom_label(aes(label = label), data = td_filter(isTip)) +
  geom_nodepoint(data = td_filter(node == 14), size = 5, color = "red")

Back to top