4

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])
1
  • You have to traverse the tree. Commented Jul 18, 2013 at 2:58

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

3 Comments

I've run the code above and the node varriableID doesn't print. Since the objective is to get a vector with predictor names, I'm working with your code to figure this out (see question). What I'm struggling with is how to update res through the recursions in a way similar to C's address operator.
I am not sure if you we use the same party package but the code above works for me. If you are interested in printing the name of the variable, just change treenode$psplit$variableID with treenode$psplit$variableName. However I am not sure if this is what you are asking. I also updated the code little bit.
I used the fuction capture.output to store the values in a data.frame for further processing
1

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.

Comments

1
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)]

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.