A Frequently asked questions
The ggtree mailing-list is a great place to get help, once you have created a reproducible example that illustrates your problem.
A.1 Installation
ggtree is released within the Bioconductor project, you need to use BiocManager to install it.
## you need to install BiocManager before using it
## install.packages("BiocManager")
library(BiocManager)
install("ggtree")
Bioconductor release is adhere to specific R version. Please make sure you are using latest version of R if you want to install the latest release of Bioconductor packages, including ggtree
. Beware that bugs will only be fixed in current release and develop branches. If you find a bug, please follow the guide18 to report it.
A.2 Basic R related
A.2.1 Use your local file
If you are new to R
and want to use ggtree
for tree visualization, please do
learn some basic R
and ggplot2
.
A very common issue is that users always copy-paste command without looking at
the function’s behavior. system.file()
was used in the treeio
and ggtree
package documentation to find files in the packages.
system.file package:base R Documentation
Find Names of R System Files
Description:
Finds the full file names of files in packages etc.
Usage:
system.file(..., package = "base", lib.loc = NULL,
mustWork = FALSE)
For users who want to use their own files, please just use relative or absolute file path (e.g. f = "your/folder/filename"
).
A.3 Aesthetic mapping
A.3.1 Inherit aes
ggtree(rtree(30)) + geom_point()
For example, we can add symbolic points to nodes with geom_point()
directly.
The magic here is we don’t need to map x
and y
position of the points by providing aes(x, y)
to geom_point()
since it was already mapped by ggtree
function and it serves as a global mapping for all layers.
But what if we provide a dataset
in a layer and the dataset
doesn’t contain column of x
and/or y
,
the layer function also try to map x
and y
and also others if you map them in ggtree
function.
As these variable is not available in your dataset
, you will get the following error:
Error in eval(expr, envir, enclos) : object 'x' not found
This can be fixed by using parameter inherit.aes=FALSE
which will disable inheriting mapping from ggtree
function.
A.3.2 Never use $
in aes
NEVER DO THIS19.
See the explaination in the ggplot2 book 2ed:
Never refer to a variable with
$
(e.g.,diamonds$carat
) inaes()
. This breaks containment, so that the plot no longer contains everything it needs, and causes problems if ggplot2 changes the order of the rows, as it does when facetting.
A.4 Text & Label
A.4.1 Tip label truncated
For rectangular/dendrogram layout tree, users can display tip labels as y-axis labels. In this case, no matter how long the labels is, they will not be truncated (see Figure 4.8C).
This reason for this issue is that ggplot2 can’t auto adjust xlim
based on added text20.
library(ggtree)
## example tree from https://support.bioconductor.org/p/72398/
read.tree(text= paste("(Organism1.006G249400.1:0.03977,(Organism2.022118m:0.01337,",
tree <-"(Organism3.J34265.1:0.00284,Organism4.G02633.1:0.00468)0.51:0.0104):0.02469);"))
ggtree(tree) + geom_tiplab() p <-
In this example, the tip labels displayed on Figure A.1A are truncated. This is because the units are in two different spaces (data and pixel). Users can use xlim
to allocate more spaces for tip labels (Figure A.1B).
+ xlim(0, 0.08) p
Another solution is to set clip = "off"
to allow drawing outside of the plot panel. We may also need to set plot.margin
to allocate more spaces for margin (Figure A.1C).
+ coord_cartesian(clip = 'off') +
p theme_tree2(plot.margin=margin(6, 120, 6, 6))
The third solution is using hexpand()
as demonstrated in session 10.5.2.
A.4.2 Modify (tip) labels
If you want to modify tip labels of the tree, you can use treeio::rename_taxa()
to rename a phylo
or treedata
object.
read.tree(text = "((A, B), (C, D));")
tree <- data.frame(label = LETTERS[1:4],
d <-label2 = c("sunflower", "tree", "snail", "mushroom"))
## rename_taxa use 1st column as key and 2nd column as value by default
## rename_taxa(tree, d)
rename_taxa(tree, d, label, label2) %>% write.tree
## [1] "((sunflower,tree),(snail,mushroom));"
If the input tree object is a treedata
instance, you can use write.beast()
to export the tree with with associated data to a BEAST compatible NEXUS file.
Renaming phylogeny tip labels seems not be a good idea, since it may introduce problems when mapping the original sequence alignment to the tree. Personally, I recommend to store the new labels as a tip annotation in treedata
object.
full_join(tree, d, by = "label")
tree2 <- tree2
## 'treedata' S4 object'.
##
## ...@ phylo:
## Phylogenetic tree with 4 tips and 3 internal nodes.
##
## Tip labels:
## [1] "A" "B" "C" "D"
##
## Rooted; no branch lengths.
##
## with the following features available:
## 'label2'.
If you just want to show different or additional information when plotting the tree, you don’t need to modify tip labels. This could be easily done via the %<+%
operator to attach the modified version of the labels and than use geom_tiplab
to display
the modified version (Figure A.2).
ggtree(tree) + xlim(NA, 3)
p <- p + geom_tiplab()
p1 <-
## the following command will produce identical figure of p2
## ggtree(tree2) + geom_tiplab(aes(label = label2))
p %<+% d + geom_tiplab(aes(label=label2))
p2 <-::plot_grid(p1, p2, ncol=2, labels = c("A", "B")) cowplot
A.4.3 Formatting (tip) labels
If you want to format labels, you need to set parse=TRUE
in geom_text
/geom_tiplab
and the label
should be string that can be parsed into expression and displayed as described in ?plotmath
.
For example, the tip labels contains two parts, species name and accession number and we want to display species name in italic, we can use command like this to format specific tip/node label (Figure A.3A):
set.seed(2019-06-24)
rtree(30)
tree <- ggtree(tree) +
p1 <- geom_tiplab(aes(subset=node==35),
label='paste(italic("species name"),
" accession number")',
parse=T) + xlim(0, 6)
Another example for formating all tip labels is demonstrated in Figure A.3B:
ggtree(tree) +
p2 <- geom_tiplab(aes(label=paste0('bold(', label,
')~italic(', node, ')')),
parse=TRUE) + xlim(0, 5)
The label
can be provided by a data.frame
that contains related information
of the taxa (Figure A.3C).
read.tree(text = "((a,(b,c)),d);")
tree <- c("Gorilla", "Pan", "Homo", "Pongo")
genus <- c("gorilla", "spp.", "sapiens", "pygmaeus")
species <- c("Africa", "Africa", "World", "Asia")
geo <- data.frame(label = tree$tip.label, genus = genus,
d <-species = species, geo = geo)
ggtree(tree) %<+% d + xlim(NA, 6) +
p3 <- geom_tiplab(aes(label=paste0('italic(', genus,
')~bolditalic(', species, ')~', geo)),
parse=T)
::plot_grid(p1, p2, p3, ncol=3, labels = LETTERS[1:3]) cowplot
A.4.4 Avoid overlapping text labels
User can use ggrepel package to repel overlapping text labels21. .
For example:
library(ggrepel)
library(ggtree)
system.file("extdata/RAxML", "RAxML_bipartitionsBranchLabels.H3", package="treeio")
raxml_file <- read.raxml(raxml_file)
raxml <-ggtree(raxml) + geom_label_repel(aes(label=bootstrap, fill=bootstrap)) +
theme(legend.position = c(.1, .8)) + scale_fill_viridis_c()
A.4.5 Bootstrap values from newick format
It’s quite command to store bootstrap
value as node label in newick
format. Visualizing node label is easy using geom_text2(aes(subset = !isTip, label=label))
.
If you want to only display a subset of bootstrap
(e.g. bootstrap > 80), you can’t simply using geom_text2(subset= (label > 80), label=label)
(or geom_label2
) since label
is a character vector, which contains node label (bootstrap value) and tip label (taxa name). If we use geom_text2(subset=(as.numeric(label) > 80), label=label)
, it will also fail since NAs
were introduced by coercion. We need to convert NAs
to logical FALSE
, this can be done by the following code:
system.file("extdata/RAxML","RAxML_bipartitions.H3", package='treeio')
nwk <- read.tree(nwk)
tr <-ggtree(tr) + geom_label2(aes(label=label, subset = !is.na(as.numeric(label)) & as.numeric(label) > 80))
Another solution is converting the bootstrap value outside ggtree
.
ggtree(tr)
q <- q$data
d <- d[!d$isTip,]
d <-$label <- as.numeric(d$label)
d d[d$label > 80,]
d <-
+ geom_text(data=d, aes(label=label)) q
A.5 Branch setting
A.5.1 Change branch length of outgroup
When outgroups are on a very long branch length (Figure A.6A), we would like to keep the out groups in the tree but ignore their branch lengths (Figure A.6B)22. This can be easily done by modifying coordination of the out groups.
read.tree("data/long-branch-example.newick")
x <- MRCA(x, 75, 76)
m <- groupClade(x, m)
y <- p1 <- ggtree(y, aes(linetype = group)) +
p <- geom_tiplab(size = 2) +
theme(legend.position = 'none')
$data[p$data$node %in% c(75, 76), "x"] <- mean(p$data$x)
pplot_grid(p1, p, ncol=2)
A.5.2 Attach a new tip to a tree
Sometimes there are known branches that are not in the tree, and we would like to have them on the tree. Another scenario is that we have a newly sequence species and would like to update reference tree with this species by inferring its evolutionary position.
Users can use phytools::bind.tip()
(Revell 2012) to attach a new tip to a tree. With tidytree, it is easy to add annotation to differentiate newly introduce and original branches and to reflect uncertainty of the added branch splits off as demonstrated in Figure A.7.
library(phytools)
library(tidytree)
library(ggplot2)
library(ggtree)
set.seed(2019-11-18)
rtree(5)
tr <-
bind.tip(tr, 'U', edge.length = 0.1, where = 7, position=0.15)
tr2 <- as_tibble(tr2)
d <-$type <- "original"
d$type[d$label == 'U'] <- 'newly introduce'
d$sd <- NA
d$sd[parent(d, 'U')$node] <- 0.05
d
as.treedata(d)
tr3 <-ggtree(tr3, aes(linetype=type)) + geom_tiplab() +
geom_errorbarh(aes(xmin=x-sd, xmax=x+sd, y = y - 0.3),
linetype='dashed', height=0.1) +
scale_linetype_manual(values = c("newly introduce" = "dashed",
"original" = "solid")) +
theme(legend.position=c(.8, .2))
A.5.3 Change colours or line types of arbitrary selected branches
If you want to colour or change line types of specific branches, you only need to prepare a data frame with variables of branch setting (e.g. selected and unselected).
set.seed(123)
rtree(10)
x <-## binary choices of colours
data.frame(node=1:Nnode2(x), colour = 'black')
d <-c(2,3,14,15), 2] <- "red"
d[
## multiple choices of line types
data.frame(node=1:Nnode2(x), lty = 1)
d2 <-c(2,5,13, 14), 2] <- c(2, 3, 2,4)
d2[
ggtree(x) + geom_label(aes(label=node))
p <-%<+% d %<+% d2 + aes(colour=I(colour), linetype=I(lty)) p
Users can use the gginnards package to manipulate plot elements for more complicated scenarios.
A.5.4 Add an arbitrary point to a branch
If you want to add an arbitrary point to a branch23, you can use geom_nodepoint
, geom_tippoint
or geom_point2
(works for both external and internal nodes) to filter selected node (end point of the branch) via the subset
aesthetic mapping and specify horizontal position by x = x - offset
aesthetic mapping, where the offset can be an absolute value (Figure A.9A) or proportion to branch length (Figure A.9B).
set.seed(2020-05-20)
rtree(10)
x <- ggtree(x)
p <-
p + geom_nodepoint(aes(subset = node == 13, x = x - .1),
p1 <-size = 5, colour = 'firebrick', shape = 21)
p + geom_nodepoint(aes(subset = node == 13, x = x - branch.length * 0.2),
p2 <-size = 3, colour = 'firebrick') +
geom_nodepoint(aes(subset = node == 13, x = x - branch.length * 0.8),
size = 5, colour = 'steelblue')
::plot_grid(p1, p2, labels=c("A", "B")) cowplot
A.6 Different x-axis labels for different facet panels
This is not supported by ggplot2 in general. However, we can just draw text labels for each panels and put the labels beyond the plot panels as demonstrated in Figure A.10.
library(ggtree)
library(ggplot2)
set.seed(2019-05-02)
rtree(30)
x <- ggtree(x) + geom_tiplab()
p <- data.frame(label = x$tip.label,
d <-value = rnorm(30))
facet_plot(p, panel = "Dot", data = d,
p2 <-geom = geom_point, mapping = aes(x = value))
p2 + theme_bw() +
p2 <- xlim_tree(5) + xlim_expand(c(-5, 5), 'Dot')
data.frame(.panel = c('Tree', 'Dot'),
d =lab = c("Distance", "Dot Units"),
x=c(2.5,0), y=-2)
+ scale_y_continuous(limits=c(0, 31),
p2 expand=c(0,0),
oob=function(x, ...) x) +
geom_text(aes(label=lab), data=d) +
coord_cartesian(clip='off') +
theme(plot.margin=margin(6, 6, 40, 6))
A.7 Plot something behind the phylogeny
The ggtree
function plot the tree structure and normally we add layers on top of the tree.
set.seed(1982)
rtree(5)
x <- ggtree(x) + geom_hilight(node=7, alpha=1) p <-
If we want the layers behind the tree layer, we can reverse the order of all the layers.
$layers <- rev(p$layers) p
Another solution is to use ggplot()
instead of ggtree()
and + geom_tree()
to add the layer of tree structure at the correct position of layer stack.
ggplot(x) + geom_hilight(node=7, alpha=1) + geom_tree() + theme_tree()
A.8 Enlarge center space in circular/fan layout tree
This question was asked several times24, and a published example can be found in https://www.ncbi.nlm.nih.gov/pubmed/27605062. Increasing percentage of center white space in circular tree is useful to avoid overlapping tip labels and to increase readibility of the tree by moving all nodes and branches further out. This can be done simply by using +xlim()
to allocate more space, just like in Figure 4.3G, or assign a long root branch that is similar to the “Root Length” parameter in FigTree.
set.seed(1982)
rtree(30)
tree <-plot_grid(
ggtree(tree, layout='circular') + xlim(-10, NA),
ggtree(tree, layout='circular') + geom_rootedge(5),
labels = c("A", "B", ncol=2)
)
A.9 Use the most distant tip from the root as the origin of the time scale
The revts
will reverse the x-axis by setting the most recent tip to 0. We can use scale_x_continuous(labels=abs)
to label x-axis using absolute values.
rtree(10)
tr <- ggtree(tr) + theme_tree2()
p <- revts(p) + scale_x_continuous(labels=abs)
p2 <-plot_grid(p, p2, ncol=2, labels=c("A", "B"))
References
Revell, Liam J. 2012. “Phytools: An R Package for Phylogenetic Comparative Biology (and Other Things).” Methods in Ecology and Evolution 3 (2): 217–23. https://doi.org/10.1111/j.2041-210X.2011.00169.x.
https://guangchuangyu.github.io/2016/07/how-to-bug-author/↩︎
https://groups.google.com/d/msg/bioc-ggtree/hViM6vRZF94/MsZT8qRgBwAJ and https://github.com/GuangchuangYu/ggtree/issues/106↩︎
https://twitter.com/hadleywickham/status/600280284869697538↩︎
https://cran.r-project.org/web/packages/ggrepel/vignettes/ggrepel.html↩︎
example from: https://groups.google.com/d/msg/bioc-ggtree/T2ySvqv351g/mHsyljvBCwAJ↩︎
https://groups.google.com/d/msg/bioc-ggtree/gruC4FztU8I/mwavqWCXAQAJ, https://groups.google.com/d/msg/bioc-ggtree/UoGQekWHIvw/ZswUUZKSGwAJ and https://github.com/GuangchuangYu/ggtree/issues/95↩︎