Today a colleague at Universidad de los Andes (where I'm currently on sabbatical, BTW) asked me how to add error bars for divergence times to the nodes of a plotted phylogeny in R.

Well, as is the case with many things, I bet that there is a ton of different ways to do this; however, the following is one very simple technique.

In the following, I have a `"phylo"`

object `tree`

; and
I also have a matrix (`CI`

) containing the times before the
present for the lower & upper confidence limits on each estimated divergence
time corresponding to the nodes of my tree. Note that these CIs have been
simulated to be intentionally assymetric - as such confidence intervals
often are:

```
library(phytools)
## here are the data:
tree
```

```
##
## Phylogenetic tree with 26 tips and 25 internal nodes.
##
## Tip labels:
## Z, Y, X, W, V, U, ...
##
## Rooted; includes branch lengths.
```

```
CI
```

```
## lower (MYBP) upper (MYBP)
## 27 111.80101 92.599420
## 28 90.13474 64.370663
## 29 48.45811 28.394226
## 30 42.77937 22.359999
## 31 83.01736 61.962733
## 32 41.48123 18.614973
## 33 26.10956 0.000000
## 34 95.60433 75.950823
## 35 88.41807 68.551308
## 36 93.32274 69.118385
## 37 84.96369 66.249093
## 38 29.45826 6.303606
## 39 72.61971 54.372320
## 40 73.15644 45.563312
## 41 65.70458 37.262456
## 42 35.86271 18.184414
## 43 34.17755 12.586219
## 44 47.11305 26.530968
## 45 50.74606 24.070106
## 46 41.64973 23.878326
## 47 58.47533 35.912961
## 48 13.19029 0.000000
## 49 35.42824 11.007959
## 50 27.73721 6.913533
## 51 15.31440 0.000000
```

Now let's plot it:

```
plotTree(tree,xlim=c(110,-5),direction="leftwards",
mar=c(4.1,1.1,1.1,1.1),ftype="i")
abline(v=seq(0,120,by=10),lty="dashed",
col=make.transparent("grey",0.5))
axis(1,at=seq(0,120,by=20))
obj<-get("last_plot.phylo",envir=.PlotPhyloEnv)
for(i in 1:tree$Nnode+Ntip(tree))
lines(x=c(CI[i-Ntip(tree),1],CI[i-Ntip(tree),2]),
y=rep(obj$yy[i],2),lwd=11,lend=0,
col=make.transparent("blue",0.4))
points(obj$xx[1:tree$Nnode+Ntip(tree)],
obj$yy[1:tree$Nnode+Ntip(tree)],pch=19,col="blue",
cex=1.8)
```

(I added a few embellishments, but it should be straightforward to pick these out.)

I like it.

As with most such plots, it will tend to look better if expored as a PDF.

Note that because my CIs are in time for the present, I decide to plot
my tree `"leftwards"`

, but then flip my *x* axis to
run from higher to lesser values using the argument value
`xlim=c(110,-5)`

.

Note also that in the example above I have assumed that the order of
the rows of `CI`

matches the order of the node indices in
the tree.

These were simulated data, obviously. The code used to simulate these values was as follows:

```
tree<-pbtree(n=26,tip.label=LETTERS[26:1],scale=100)
h<-sapply(1:tree$Nnode+Ntip(tree),nodeheight,tree=tree)
CI<-cbind(h-runif(n=length(h),min=10,max=20),h+runif(n=length(h),
min=5,max=10))
CI[CI>max(nodeHeights(tree))]<-max(nodeHeights(tree))
CI<-max(nodeHeights(tree))-CI
rownames(CI)<-1:tree$Nnode+Ntip(tree)
colnames(CI)<-paste(c("lower","upper"),"(MYBP)")
```

Dear Liam,

ReplyDeleteHow can I get the matrix of CI from a posterior distribution of trees (empirical data)?

Thanks,

Aparna