Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Consolidate party rules

Tags:

r

party

A simple example

>library(partykit)
> partykit:::.list.rules.party(ctree(Petal.Length~.,data=iris))
                                                                                                     2 
                                                                                  "Petal.Width <= 0.6" 
                                                                                                     6 
                  "Petal.Width > 0.6 & Sepal.Length <= 6.2 & Petal.Width <= 1.3 & Sepal.Length <= 5.5" 
                                                                                                     7 
                   "Petal.Width > 0.6 & Sepal.Length <= 6.2 & Petal.Width <= 1.3 & Sepal.Length > 5.5" 
                                                                                                     ....

For example, in the second rule, the two occurrences of Sepal.Length can be consolidated into Sepal.Length<=5.5

So, is there a way to consolidate the rules?

like image 383
qoheleth Avatar asked Dec 16 '25 13:12

qoheleth


2 Answers

In the plot of the tree below, on the way to node 6 (the node whose rules you reference in your question) we first keep only points with Petal.Width > 0.6. But even then node 6 doesn't include all remaining points with Sepal.Length <= 5.5, but only those that also have Petal.Width <= 1.3. In other words, there's an intervening Petal.Width split between the two Sepal.Length splits, so the first Sepal.Length split isn't redundant.

m1 = ctree(Petal.Length~.,data=iris)
plot(m1)

enter image description here

like image 108
eipi10 Avatar answered Dec 19 '25 07:12

eipi10


There my be a more efficient way, but this functions may give you what you want:

consolidate_rules <- function(tree){
  split.vars <- colnames(tree$node$info$criterion)
  split <- partykit:::.list.rules.party(tree)
  new.split <- c()

  for(i.split in seq_along(split)) {
   for (i.split.var in split.vars) {
    x0 <- split[i.split]
    x1 <- strsplit(x0, " & ")
    x2 <- grep(i.split.var, x1[[1]], value = TRUE)
    x3l <- strsplit(grep("<=", x2, value = TRUE), " <= ") # lower than
    x3g <- strsplit(grep(">", x2, value = TRUE), " > ")  # greater
    x3e <- strsplit(grep(" %in% ", x2, value = TRUE), "%in%")  # elements
    x4 <- c()

    if (length(x3e) != 0) {
      b <- sapply(x3e, "[[", 2)
      b1 <- gsub('"', '', b)
      b2 <- gsub("[c( )]", "", b1)
      b3 <- gsub("(NA,)|(,NA)", "", b2)
      b4 <- unique(strsplit(paste0(b3, collapse = ","), ",")[[1]])
      x4 <- paste0(i.split.var, ' %in% c("',
                   paste0(b4, collapse = '", "'),'")')
    }

    if (length(x3l) != 0) {
      x4 <- paste0(i.split.var, " <= ",
                   min(as.numeric(sapply(x3l, "[[", 2))))
    }
    if (length(x3g) != 0) {
      x4 <- paste0(x4, ifelse(length(x4) > 0 ," & ",""),
                   i.split.var, " > ",
                   max(as.numeric(sapply(x3g, "[[", 2))))
    }

    tmp <- paste0(if(!is.null(new.split[i.split]) &&
                  !is.na(new.split[i.split]) &
                  length(x4) >0) {" & "}, x4)

    new.split[i.split] <- 
      paste0(if(!is.null(new.split[i.split]) &&
            !is.na(new.split[i.split])) {new.split[i.split]},
             tmp)

    rm(x0, x1, x2, x3l, x3g, x3e, x4)
   }
 }
 names(new.split) <- names(split)
 return(new.split)
}

You can call the function with:

ct <- ctree(Petal.Length~.,data=iris)
consolidate_rules(ct)

For the node 6 the result looks like this:

6 
                           "Sepal.Length <= 5.5 & Petal.Width <= 1.3 & Petal.Width > 0.6"

As the result is "just" a string with the rules, I don't know if you can use it in the same way as a .list.rules.party object. But i hope this mioght help you.

like image 20
Jakob Gepp Avatar answered Dec 19 '25 05:12

Jakob Gepp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!