一个简单的例子
>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"
....
例如,在第二条规则中,Sepal.Length
的两次出现可合并为Sepal.Length<=5.5
那么,有没有办法整合规则?
答案 0 :(得分:1)
在下面树的图中,在前往节点6(您在问题中引用其规则的节点)的路上,我们首先只保留带有Petal.Width
&gt;的点。 0.6。但即便如此,节点6也不包括{em>所有剩余点Sepal.Length
<= 5.5,而只包括那些Petal.Width
<= 1.3的点。换句话说,两个Petal.Width
拆分之间存在介入的Sepal.Length
拆分,因此第一个Sepal.Length
拆分不是多余的。
m1 = ctree(Petal.Length~.,data=iris)
plot(m1)
答案 1 :(得分:1)
我有一种更有效的方法,但这个功能可能会给你你想要的东西:
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)
}
您可以使用以下方式调用该函数:
ct <- ctree(Petal.Length~.,data=iris)
consolidate_rules(ct)
对于节点6,结果如下所示:
6
"Sepal.Length <= 5.5 & Petal.Width <= 1.3 & Petal.Width > 0.6"
结果是“只是”一个包含规则的字符串,我不知道你是否可以像.list.rules.party
对象一样使用它。
但我希望这个mioght会帮助你。
答案 2 :(得分:0)
一个简单的版本:
"Petal.Width > 0.6 & Sepal.Length <= 6.2 & Petal.Width <= 1.3 & Sepal.Length <= 5.5" %>%
str_split(' & ') %>% unlist() %>% str_split(' ') %>%
lapply(function(x) data.frame(var = x[1], cond = x[2], value = tail(x, -2) %>% paste(collapse = ' '))) %>% bind_rows() %>%
group_by(var, cond) %>%
filter(
if (str_detect(unique(cond), '<')) 1:n() == which.min(as.numeric(value))
else if (str_detect(unique(cond), '>')) 1:n() == which.max(as.numeric(value))
else 1:n() == which.min(str_count(value, ','))
) %>%
apply(1, paste, collapse = ' ') %>% paste(collapse = ' & ')
[1] "Petal.Width > 0.6 & Petal.Width <= 1.3 & Sepal.Length <= 5.5"
通过使用&
作为标记来拆分规则,然后将每个元素(例如:Petal.Width > 0.6
)再次拆分为其三个组成部分(例如变量Petal.Width
,条件>
和值0.6
)。我将所有内容放入一个数据框,按变量和条件分组,然后根据条件选择合适的元素。最后,我先逐行折叠,然后再折叠成一个字符串。
我今天想出了它,所以我还没有对其进行彻底的测试,但是应该可以。它需要dplyr
和stringr
软件包。请注意,该代码仅适用于一条规则,但是您可以将其与带有sapply()
的字符串向量一起使用。