user2498497
user2498497

Reputation: 703

Plot a binary tree in R from a list

I have a list that I would like to plot it into a tree. This is what the list looks like:

> tree_list
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
[1]  2  9 10

[[1]][[1]][[2]]
[1] 5 8

[[1]][[2]]
[1] 1 3 4 6


[[2]]
[1] 7

The integers 1:10 are the nodes of the tree. The [[1]] or [[2]] denotes left or right to the tree. Thanks!

Upvotes: 0

Views: 959

Answers (1)

MrFlick
MrFlick

Reputation: 206167

Well, i've written a very ugly function that seems to do it. There must be a better way. Here I basically create a fake "tree" object. Then i try to use the default plot.tree and text.tree from library(tree). Turns out I had to add in a bunch of crazy values and attributes to be convincing enough to run without error. And i'm not even sure this is the behavior you want.

library(tree)
gettree<-function(tree_list) {
    flatten<-function(x, node=1) {
        if(is.list(x)) {
            sub<-do.call(rbind, 
               lapply(1:2, function(i) flatten(x[[i]], node=node*2+i-1) ))
            rbind(data.frame(name=paste("split",node), nodeid=node,
               N=sum(as.numeric(sub$n)), n=0, vals=NA), sub)
        } else {
            data.frame(name="<leaf>", nodeid=node, N=0, n=length(x), vals=I(list(x)))
        }
    }
    ff<-flatten(tree_list)
    is.leaf <- grepl("<leaf>",ff$name)
    df<-data.frame(
        var=ff$name,
        n=pmax(ff$N,ff$n), dev=ff$n,
        yval=factor(sapply(ff$vals, paste, collapse=","))
    )
    df$splits<-matrix(cbind(ifelse(!is.leaf, "","left"), 
        ifelse(!is.leaf, "","right")), ncol=2,
        dimnames=list(NULL, c("cutleft","cutright")))
    rownames(df)<-ff$nodeid
    whmx <- do.call(rbind, mapply(cbind, seq_along(ff$vals), ff$vals))
    y<-factor(whmx[!is.na(whmx[,2]),2])
    wh<-as.numeric(whmx[!is.na(whmx[,2]),1])
    yf<-factor(df$yval)
    yprob <- matrix(0, ncol=nlevels(yf), nrow=length(yf))
    yprob[cbind(seq_along(yf), as.numeric(yf))]<-1
    df$yprob <- yprob
    structure(list(frame=df,y=y, where=wh),  class="tree", ylevels=levels(yf))
}

Once we've defined that function, we can run it with your data.

tree_list<-list(list(list(c(2,9,10), c(5,8)), c(1,3,4,6)), 7)

mt<-gettree(tree_list)

plot(mt, type="uniform")
text(mt, splits=F)

and that makes this plot

binary tree visualization

It's still quite rough around the edges, but if you're really interested perhaps you could clean it up.

Upvotes: 2

Related Questions