Question

I've checked binary tree class methods, and How to extract tree structure from ctree function? (which was helpful understanding S4 object structure and slots), but it's still unclear how to get to the final predictors of a ctree object. For rpart, I'd use something like

 extract_preds <- function( tt ){
   leaves <- tt$frame$var == '<leaf>'
   as.character( unique( tt$frame$var[ leaves==F ] ) )
 }

Is there a similar shortcut available, or do I have to write a recursive function to traverse the ctree object and extract the predictors? That, or a regex-fest with the print output? Thanks.

UPDATE: using baydoganm's code below. Still have to figure out how to update res properly through the recursions:

 library(party)

 ctree_preds <- function(tr,vnames){    
    res <- character(0)
    traverse <- function(treenode,vnames,res){
    if(treenode$terminal){
        return(res)
    } else {
        res <- c(res,vnames[treenode$psplit$variableID])
        traverse(treenode$left , vnames, res )
        traverse(treenode$right, vnames, res )
        }
    }
    traverse(tr,vnames,res)
    return(unique(res))
 }

 airq <- subset(airquality, !is.na(Ozone))
 airct <- ctree(Ozone ~ ., data = airq,
                         controls = ctree_control(maxsurrogate = 3))
 plot(airct)

 ctree_preds(airct@tree,names(airq)[-1])
Was it helpful?

Solution

Below is the script I implemented to traverse the tree from a ctree object. I use the same example in the party package which is airct dataset.

require(party)
data(airquality)

traverse <- function(treenode){
    if(treenode$terminal){
        bas=paste("Current node is terminal node with",treenode$nodeID,'prediction',treenode$prediction)
        print(bas)
        return(0)
    } else {
        bas=paste("Current node",treenode$nodeID,"Split var. ID:",treenode$psplit$variableName,"split value:",treenode$psplit$splitpoint,'prediction',treenode$prediction)
        print(bas)
}
traverse(treenode$left)
traverse(treenode$right)
}

airq <- subset(airquality, !is.na(Ozone))
airct <- ctree(Ozone ~ ., data = airq,
controls = ctree_control(maxsurrogate = 3))
plot(airct)

traverse(airct@tree)

This function, traverse, just traverses the tree in a depth-first order. You can change the order of the traversal by changing the recursive part.

Moreover, if you want to return other node characteristics, I would recommend checking the structure of the ctree object.

edit: Minor code revisions.

OTHER TIPS

The mlmeta R package's ctree2sas() function converts fitted ctree models to SAS code. It can be easily adapted to other languages and is generally instructive on the internals of the object.

split <- 
c(cart@tree$psplit$splitpoint , cart@tree$right$psplit$splitpoint , cart@tree$left$psplit$splitpoint , cart@tree$right$right$psplit$splitpoint , cart@tree$right$left$psplit$splitpoint , cart@tree$left$right$psplit$splitpoint , cart@tree$left$left$psplit$splitpoint , cart@tree$right$right$right$psplit$splitpoint , cart@tree$right$right$left$psplit$splitpoint , cart@tree$right$left$right$psplit$splitpoint , cart@tree$right$left$left$psplit$splitpoint , cart@tree$left$right$right$psplit$splitpoint , cart@tree$left$right$left$psplit$splitpoint , cart@tree$left$left$right$psplit$splitpoint , cart@tree$left$left$left$psplit$splitpoint , cart@tree$right$right$right$right$psplit$splitpoint , cart@tree$right$right$right$left$psplit$splitpoint , cart@tree$right$right$left$right$psplit$splitpoint , cart@tree$right$right$left$left$psplit$splitpoint , cart@tree$right$left$right$right$psplit$splitpoint , cart@tree$right$left$right$left$psplit$splitpoint , cart@tree$right$left$left$right$psplit$splitpoint , cart@tree$right$left$left$left$psplit$splitpoint , cart@tree$left$right$right$right$psplit$splitpoint , cart@tree$left$right$right$left$psplit$splitpoint , cart@tree$left$right$left$right$psplit$splitpoint , cart@tree$left$right$left$left$psplit$splitpoint , cart@tree$left$left$right$right$psplit$splitpoint , cart@tree$left$left$right$left$psplit$splitpoint , cart@tree$left$left$left$right$psplit$splitpoint , cart@tree$left$left$left$left$psplit$splitpoint , cart@tree$left$left$left$left$left$psplit$splitpoint , cart@tree$left$left$left$left$right$psplit$splitpoint , cart@tree$left$left$left$right$left$psplit$splitpoint , cart@tree$left$left$left$right$right$psplit$splitpoint , cart@tree$left$left$right$left$left$psplit$splitpoint , cart@tree$left$left$right$left$right$psplit$splitpoint , cart@tree$left$left$right$right$left$psplit$splitpoint , cart@tree$left$left$right$right$right$psplit$splitpoint , cart@tree$left$right$left$left$left$psplit$splitpoint , cart@tree$left$right$left$left$right$psplit$splitpoint , cart@tree$left$right$left$right$left$psplit$splitpoint , cart@tree$left$right$left$right$right$psplit$splitpoint , cart@tree$left$right$right$left$left$psplit$splitpoint , cart@tree$left$right$right$left$right$psplit$splitpoint , cart@tree$left$right$right$right$left$psplit$splitpoint , cart@tree$left$right$right$right$right$psplit$splitpoint , cart@tree$right$left$left$left$left$psplit$splitpoint , cart@tree$right$left$left$left$right$psplit$splitpoint , cart@tree$right$left$left$right$left$psplit$splitpoint , cart@tree$right$left$left$right$right$psplit$splitpoint , cart@tree$right$left$right$left$left$psplit$splitpoint , cart@tree$right$left$right$left$right$psplit$splitpoint , cart@tree$right$left$right$right$left$psplit$splitpoint , cart@tree$right$left$right$right$right$psplit$splitpoint , cart@tree$right$right$left$left$left$psplit$splitpoint , cart@tree$right$right$left$left$right$psplit$splitpoint , cart@tree$right$right$left$right$left$psplit$splitpoint , cart@tree$right$right$left$right$right$psplit$splitpoint , cart@tree$right$right$right$left$left$psplit$splitpoint , cart@tree$right$right$right$left$right$psplit$splitpoint , cart@tree$right$right$right$right$left$psplit$splitpoint , cart@tree$right$right$right$right$right$psplit$splitpoint)

split <- split[order(split)]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top