3
$\begingroup$

I have a dataset that I wish to convert to tree or phylo format like in the ape package, in order to plot the phylogenetic tree. It is formatted like a list of edges and species names for the leaves. The dataset is quite large, but I have made an example dataset that represents it:

df <- data.frame(c(8,8,7,6,6,7,9,9,9),
                c(1,2,3,4,5,6,7,8,9),
                c(9, 9, 12, 14, 17, 19, 21, 23, 9),
                c("a","b","c","d","e", "node1", "node2", "node3", "node4"))
names(df) <- c("parent","node","branch.length", "label")

I wish to plot it as a rooted phylogenetic tree using the ape package, but I can't figure out how to convert it to for example a newick string. I have tried to look at solutions both in R and Python, but I can't figure it out. Does anyone have any idea how this can be done?

Additional information: I also have two other vectors, one contains the length of each edge, and one containing the age of the child node, equal to the sum of all edge length from that child to any leaf of the tree. It would be great if this could be included, but not neccessary for the plotting as it is only illustrative.

Thanks!

Update

I am using R version 4.1.2. One of my attempts at translating my data to Newick code (as i understand this could include the branch lengths), using one of [these answers]. I don't understand what goes wrong, but I have not worked with Newick code before so I am not very experienced with this. (https://biology.stackexchange.com/questions/37057/construct-phylogeny-form-edgelist):

df <- data.frame(c(8,8,7,6,6,7,9,9,9),
                c(1,2,3,4,5,6,7,8,9),
                c(9, 9, 12, 14, 17, 19, 21, 23, 9),
                c("a","b","c","d","e", "node1", "node2", "node3", "node4"))
names(df) <- c("parent","node","branch.length", "label")
tree_data <- df
str(tree_data)

tree_data$newick = paste(tree_data$label,':',signif(tree_data$branch.length,3),sep="")
nparents = 2
  while(nparents > 1){
  leaf = setdiff(tree_data$node,tree_data$parent)
  parent_leaf = unique(tree_data$parent[!is.na(match(tree_data$node,leaf))])
  index_remove = integer(0)
  for(i in 1:length(parent_leaf)){
parent_children = tree_data$node[which(tree_data$parent == parent_leaf[i])]
all_children_in_leaf = all(parent_children %in% leaf)
if(all_children_in_leaf==T){
  index_remove = c(index_remove,match(parent_children,tree_data$node))
  tree_data$newick[which(tree_data$node==parent_leaf[i])] = paste("(",paste(tree_data$newick[match(parent_children,tree_data$node)],collapse=" , "),")",tree_data$newick[which(tree_data$node==parent_leaf[i])] ,sep = " ")
}
  }
  tree_data = tree_data[-index_remove,]
  parent_next = unique(tree_data$parent[!is.na(match(tree_data$node,leaf))])
  nparents = length(parent_next)
  if (nparents==1) newick_code = paste("(",paste(tree_data$newick,collapse=","),")",colnames(tree_data)[parent_next],";",sep = " ")
}


tree <- ape::read.tree(text = newick_code)

plot.phylo(tree)

I don't get an error any more, but I get some unexpected output:

The output I get

This is what I would expect, all nodes that are not single letters are inner nodes, not leaves:

The output I want

I really appreciate any help!

$\endgroup$
9
  • 1
    $\begingroup$ There is an answer to more or less the same question in biology.stackexchange.com. $\endgroup$ Mar 7, 2023 at 22:22
  • $\begingroup$ Thank you for the answer, I have taken a look at the answers but none of them seem to work for me. (all return errors after reformatting to the data format they used) Nikunj Goel's answer of writing a code to translate to Newick code and include the branch lengths is what I have tried to do myself, but it is challenging as I am not very familiar with it. $\endgroup$
    – helle
    Mar 10, 2023 at 7:22
  • $\begingroup$ Hi @Helle, can you provide a few lines of codes as well as the errors you are getting. Include the version of R you are using. Those answers were published 7 yrs ago most likely you will have to adjust your code a bit to make it compatible with current standards. $\endgroup$
    – Macintosh
    Mar 10, 2023 at 9:09
  • $\begingroup$ @Macintosh I have updated it now :-) $\endgroup$
    – helle
    Mar 10, 2023 at 10:07
  • $\begingroup$ the error comes from colnames(Adj)[parent_next]: Adj is not defined and should refer to the correct table. $\endgroup$
    – Macintosh
    Mar 10, 2023 at 12:42

1 Answer 1

4
$\begingroup$

The following example uses python to generate the newick string. You can than import that in R for further analysis.

Please keep in mind that you can not use self reference for node4 (9,9,9), so I changed this to 'Root'.

from ete3 import Tree
import pandas as pd

df = pd.DataFrame({'parent': [8, 8, 7, 6, 6, 7, 9, 9, 'Root'],
                   'node': [1, 2, 3, 4, 5, 6, 7, 8, 9],
                   'branch.length': [9, 9, 12, 14, 17, 19, 21, 23, 9],
                   'label': ['a', 'b', 'c', 'd', 'e', 'node1', 'node2', 'node3', 'node4']})


parent_child_list = df[['parent', 'node', 'branch.length']].apply(tuple, axis=1).tolist()
tree = Tree.from_parent_child_table(parent_child_list)
newick_str = tree.write(format=1)

newick_str:

'(((3:12,(4:14,5:17)6:19)7:21,(1:9,2:9)8:23)9:9);'
$\endgroup$
1
  • $\begingroup$ Thank you! Exactly what I was looking for. $\endgroup$
    – helle
    Mar 11, 2023 at 11:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.