An R-sig-phylo list participant asks:
“I am trying to plot the results of an ancestral state reconstruction of 4 discrete traits onto a single phylogeny. What I would like to do is have a pie on each node split into 4 equal segments, and then have the colour of each segment correspond to the probable trait value at that node (black for present, white for absent, for example).
"Would anyone be able to offer me some guidance as to how to colour the segment based on a dataframe or matrix of trait values rather than the position of the segment in the pie (which is how the piechart legend seems to do it)?”
So far as I can tell, this cannot be done using the standard ape function
for plotting pies at nodes, nodelabels
; however it is pretty
easy to do with a basic understanding of the internal machinations of the
nodelabels
function. Here is how.
First, let's simulate a tree and presence/absence (binary 0/1) data for four characters:
library(phytools)
## simulate tree
tree<-pbtree(n=26,tip.label=LETTERS[26:1],scale=1)
## transition matrix
Q<-matrix(c(-1,1,1,-1),2,2)
rownames(Q)<-colnames(Q)<-0:1
## simulate character histories
## making "0" the ancestral state
trees<-replicate(sim.history(tree,Q,anc="0"),n=4,simplify=FALSE)
class(trees)<-"multiPhylo"
## pull out the states at nodes
N<-sapply(trees,function(x) as.numeric(getStates(x,"nodes")))
rownames(N)<-1:tree$Nnode+Ntip(tree)
The end product of this simulation is a phylogeny (tree
) and a
matrix containing 0
s and 1
s for each node in the
tree. This would normally be our input for the next stage, which is our
actual plotting exercise
tree
##
## Phylogenetic tree with 26 tips and 25 internal nodes.
##
## Tip labels:
## Z, Y, X, W, V, U, ...
##
## Rooted; includes branch lengths.
N
## [,1] [,2] [,3] [,4]
## 27 0 0 0 0
## 28 0 0 0 1
## 29 0 0 1 1
## 30 0 0 1 1
## 31 1 0 1 1
## 32 0 1 1 1
## 33 1 0 1 0
## 34 0 0 1 0
## 35 0 0 0 1
## 36 0 0 0 1
## 37 0 0 0 1
## 38 0 0 0 1
## 39 0 0 0 0
## 40 0 1 0 0
## 41 0 1 0 0
## 42 1 1 0 0
## 43 1 0 1 0
## 44 0 1 0 0
## 45 0 1 0 0
## 46 0 1 0 0
## 47 0 0 0 0
## 48 1 0 0 0
## 49 0 0 0 0
## 50 0 0 1 0
## 51 0 0 1 0
OK, here we go. For this, we'll get the help of the package plotrix to plot floating pie charts at all the nodes of the tree:
plotTree(tree)
## first part borrowed from nodelabels
lastPP<-get("last_plot.phylo",envir=.PlotPhyloEnv)
node<-(lastPP$Ntip+1):length(lastPP$xx)
X<-lastPP$xx[node]
Y<-lastPP$yy[node]
h<-par()$usr[2]
for(i in 1:length(node))
floating.pie(X[i],Y[i],rep(0.25,4),radius=0.015*h,
col=c("white","black")[N[i,]+1])
It is also straightforward to do the tips as well in the same way:
## preliminaries
## pull out the states at tips
T<-sapply(trees,function(x) as.numeric(getStates(x,"tips")))
rownames(T)<-tree$tip.label
## plot
plotTree(tree,offset=1)
lastPP<-get("last_plot.phylo",envir=.PlotPhyloEnv)
node<-(lastPP$Ntip+1):length(lastPP$xx)
X<-lastPP$xx[node]
Y<-lastPP$yy[node]
h<-par()$usr[2]
for(i in 1:length(node))
floating.pie(X[i],Y[i],rep(0.25,4),radius=0.015*h,
col=c("white","black")[N[i,]+1])
X<-lastPP$xx[1:Ntip(tree)]
Y<-lastPP$yy[1:Ntip(tree)]
for(i in 1:Ntip(tree))
floating.pie(X[i],Y[i],rep(0.25,4),radius=0.015*h,
col=c("white","black")[T[i,]+1])
That's it.
Hello, thanks for the blog, very interesting and insightful! I would like to know in this kind of tree generated from binary matrix, what would be the meaning of a scale bar = 1? Thank you vey much!
ReplyDelete"Would anyone be able to offer me some guidance as to how to colour the segment based on a dataframe or matrix of trait values rather than the position of the segment in the pie (which is how the piechart legend seems to do it)? binary options trading
ReplyDelete