Search code examples
rdendrogramveganbipartitephylogeny

Combine dendrogram with bipartite graphs in R (tanglegram)


I am currently working on creating a tanglegram where species reared are on one side and substrate reared on is on the other side. However, I need the output to also be a tanglegram, having each side of the chart be the tips of a dendogram. I currently have phylogenies of both the species and substrates in Newick formats.

I successfully used the 'ape' package and the plot.phylo() function to generate the 2 phylogenies. I then used the following code from this post to export the order of tips:

tree <- ladderize(tree, right = FALSE)
is_tip <- tree$edge[,2] <= length(tree$tip.label)
ordered_tips <- tree$edge[is_tip, 2]
x<-tree$tip.label[ordered_tips]
write.csv(x,file="test.csv",sep ="\t")

I then used the order of the tips to generate a matrix for use in the 'bipartite' package.

However, of course, the spacing on the bipartite graph doesn't match up with the spacing on the dengdrograms, so I can't just copy/paste them next to one another in an outside image manipulation program. I am wondering if there is a way that I can generate a chart that combines the dendrograms and bipartite graph to make a tanglegram in rstudio?

Here is a simplified visual example of what I am hoping to do:

I am looking to combine 2 phylogenetic trees that, for example, look like this

tree1<-read.tree(text="((C,B),A);")
plot(tree1)

Output: tree1

tree2<-read.tree(text="((G,F),(E,D));")
plot(tree2)

Output: tree2

With a bipartite graph

web = matrix(
c(0, 5, 0, 10, 10, 0, 0, 3, 0, 0, 0, 1),
nrow=4,
ncol=3,
byrow = TRUE,
dimnames = list(c("D","E","F","G"),c("A","B","C"))) 
plotweb(web,method="normal",empty="false",text.rot="90")

Output: bipartite plot

To instead generate a plot that looks like this (I just did the following in an image editor, the expansive dataset I am actually using is far larger)

Desired output: tanglegram


Solution

  • A way to draw a tanglegram with trees where the tip labels do not match is to use an association matrix - a matrix that lists corresponding taxa in the respective trees. Using the provided data, the following code will extract the names from columns and rows and the respective weight.

     assoc = data.frame()
     temp = matrix(NA, ncol = 3, nrow = ncol(web))
    
     for(i in 1:nrow(web)){
         for(j in 1:ncol(web)){
             temp[j,] = c(rownames(web)[i], colnames(web)[j], web[i,j])
         }
         assoc = rbind(assoc, temp)
     }
    head(assoc)
      V1 V2 V3
     1  D  A  0
     2  D  B  5
     3  D  C  0
     4  E  A 10
     5  E  B 10
    

    The last column can be used to set weight of the connecting lines between taxa.

    library(ape)
    cophyloplot(tree2, tree1, assoc[,1:2], lwd = as.numeric(as.character(assoc[,3])), space = 15)
    

    enter image description here