Wednesday, January 25, 2017

plotTree.barplot with more user options, including stacked bars for multiple input traits

In response to a user comment I have added a feature to plotTree.barplot to permit multiple traits or values to be plotted for each species - either using stacked bars, or by plotting the bars side-by-side.

The update can be seen here. The problem turned out to be a little bit mroe complicated then it seemed it first, mainly because of a quirk in barplot that means that the object returned by boxplot (which I then use to correctly space the tips of the plotted tree) differs depending on whether the input data come in the form of a vector of single values or a matrix, &, if the latter, whether the argument beside=TRUE is selected or not.

Here's a quick & dirty demo. These data are (simulated to represent) relative frequencies - said dietary fraction of three different food types - so stacking of our bars is appropriate:

library(phytools)
packageVersion("phytools")
## [1] '0.5.70'
tree
## 
## Phylogenetic tree with 26 tips and 25 internal nodes.
## 
## Tip labels:
##  A, B, C, D, E, F, ...
## 
## Rooted; includes branch lengths.
X
##        plant  vertebrate invertebrate
## A 0.31086049 0.212175943   0.47696356
## B 0.15404215 0.440976975   0.40498087
## C 0.26982034 0.450834511   0.27934515
## D 0.12260206 0.358475976   0.51892197
## E 0.29979068 0.129743168   0.57046615
## F 0.20163877 0.440001107   0.35836012
## G 0.05465514 0.410528162   0.53481670
## H 0.47392116 0.121520364   0.40455848
## I 0.44344594 0.101251541   0.45530252
## J 0.24839375 0.268691107   0.48291514
## K 0.12309160 0.101699889   0.77520851
## L 0.24010676 0.065417274   0.69447597
## M 0.23424489 0.226431850   0.53932326
## N 0.40030662 0.057542453   0.54215092
## O 0.15332681 0.023255378   0.82341781
## P 0.44389924 0.491496743   0.06460401
## Q 0.27010640 0.292077796   0.43781581
## R 0.21643656 0.208244073   0.57531937
## S 0.19650159 0.317376110   0.48612230
## T 0.01261411 0.427646672   0.55973922
## U 0.32707264 0.164682573   0.50824478
## V 0.28931830 0.126987763   0.58369394
## W 0.08407750 0.252999348   0.66292315
## X 0.28631262 0.004105909   0.70958147
## Y 0.38118921 0.206806916   0.41200387
## Z 0.07941718 0.074216139   0.84636668
plotTree.barplot(tree,X)

plot of chunk unnamed-chunk-1

Or, we can plot the bars side-by-side:

plotTree.barplot(tree,X,args.barplot=list(beside=TRUE,xlim=c(0,1),
    legend.text=TRUE,space=c(0,1.2),args.legend=list(x=1,y=17)))

plot of chunk unnamed-chunk-2

Note that beside=FALSE is not a good option if our data have both positive & negative values as this can produce a weird result. For instance:

Y
##         [,1]        [,2]        [,3]
## A  0.7618018  2.59661203 -0.23590050
## B  0.8548063  1.40920654  0.73019040
## C -1.1970456  1.09259205  0.56974523
## D -0.4355176  2.31904920 -1.18347277
## E  2.2923226  2.35986558 -3.22201293
## F  2.5004466  3.98754763 -2.68168275
## G  2.7103706  1.94742983 -1.81626643
## H  1.4677625  1.90001387 -2.78720751
## I  1.5596683  4.57540030 -0.17596327
## J  1.5259543  5.22197986 -0.50073032
## K  1.4834068  4.99761663 -0.35070911
## L  1.3819468  4.84211948 -0.49581275
## M  1.4874512  4.99309837 -0.06583491
## N  0.3560632  3.50340705 -0.95027035
## O -0.2002478  3.80948866 -0.60808238
## P -0.9702761  3.93130784 -3.55745209
## Q -0.2638056  2.81862255 -2.47669725
## R  0.6922559  3.11378711 -3.53855007
## S -0.5630365  3.80538588 -2.87224419
## T  0.7185199  3.63159681 -0.96902150
## U  0.2464106  3.45631197 -0.05955653
## V -0.9173568  5.08132488 -3.08922774
## W -0.5006388  4.79906054 -3.26551534
## X  0.6836688  4.47601771 -3.28019095
## Y -0.5106440 -1.65927057 -0.89645983
## Z  0.3405579 -0.02014156 -0.76899774
plotTree.barplot(tree,Y)

plot of chunk unnamed-chunk-3

If one is determined to use a barplot for these kind of data, I would recommend beside=TRUE which produces a more sensible result:

plotTree.barplot(tree,Y,args.barplot=list(beside=TRUE,space=c(0,1.2)))

plot of chunk unnamed-chunk-4

That's it.

15 comments:

  1. Hi Liam,

    Great function! Would it be a simple addition to allow error bars to be plotted over this plot so that the variance of the trait can be better visualized? Any advice would be appreciated.

    ReplyDelete
    Replies
    1. Hi Jacob. If you update to current version of phytools on GitHub you can modify any arguments to barplot using args.barplot. You can also add features to the plot after plotting, such as error bars as you suggest. You may also be interested in the function plotTree.boxplot which plots a boxplot next to a tree in a similar way. - Liam

      Delete
  2. Liam, it´s possible to use apply some function like tiplabels() to display some categorical information about species? (as you show elsewhere http://lukejharmon.github.io/ilhabela/instruction/2015/07/03/ancestral-states-2/)

    ReplyDelete
  3. Hi

    I learn a lot of things from your post , thank you. I am wondering if you are an implemented code in to have a bar plot with two y variables (beside =T). I have two variables : genome size(Mb) and gene density(genes/Mb, the plot is not so meaningful if i get them in only one y axiz when I use your plotTree.barplot code

    ReplyDelete
  4. Hi,
    thank you so much for your posts! I was wondering if it's possible to use stacked bars with plotTree.wBars?

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Hi Liam

    Firstly, thank you for this website it is a great resource of tremendous help

    When I try and create a stacked bar plot as above I receive the following error message

    "Error in plot.window(xlim = xlim, slim = slim, asp = asp):
    need finite 'slim' values"

    Any help you can give regarding this error message will be greatly appreciated!

    ReplyDelete
    Replies
    1. Edit: "Error in plot.window(xlim = xlim, ylim = ylim, asp = asp):
      need finite 'ylim' values"

      Delete
    2. Do you have the latest phytools version? If so, you could try sending me your R workspace & the commands producing the error and I could try to figure it out for you.

      Delete
    3. I'm sure this has been resolved, but I had a similar problem and wanted to share in case other folks came across this issue as well. I solved it by removing the spaces between the genus and species epithet in my dataset (changing "Genus species" to "Genus_species"). Hope that helps anyone else with a similar problem!

      Delete
  7. Hi Liam,

    How do you change the position of the scale at the bottom of the graph and for 100% stacked bar graphs that take up the whole panel is it not possible to add a legend?

    ReplyDelete
  8. Hi Liam,
    Your package phytools is really amazing! So far, I had no problem in plotting metadata associated to my phylogenetic trees, but I'am struggling to combine the results of a dottree and a plotTree.barplot on the same tree. I'm playing with margines and ylim or xlim but it is not straitforward. If you have a solution, I would gladly take it. Thank in advance.
    JC

    ReplyDelete
  9. Hi Liam,

    Thank you for your wonderful tutorials! Have you seen a way to combine a barplot with a circular tree? Apologies if I have missed this.

    Thanks in advance,

    ReplyDelete

Note: due to the very large amount of spam, all comments are now automatically submitted for moderation.