J48树中的属性及其值(RWeka)

时间:2015-08-23 15:37:30

标签: r j48

如果您运行以下内容:

library(RWeka) 
data(iris) 
res = J48(Species ~., data = iris)

res将是继承自J48的班级Weka_tree的列表。如果你打印它

R> res
J48 pruned tree
------------------

Petal.Width <= 0.6: setosa (50.0)
Petal.Width > 0.6
|   Petal.Width <= 1.7
|   |   Petal.Length <= 4.9: versicolor (48.0/1.0)
|   |   Petal.Length > 4.9
|   |   |   Petal.Width <= 1.5: virginica (3.0)
|   |   |   Petal.Width > 1.5: versicolor (3.0/1.0)
|   Petal.Width > 1.7: virginica (46.0/1.0)

Number of Leaves  :     5

Size of the tree :  9

我想从右到左按顺序获取属性及其值。所以对于这种情况:

Petal.Width, Petal.Width, Petal.Length, Petal.Length.

我尝试将res输入到一个因子并运行命令:

str_extract(paste0(x, collapse=""), perl("(?<=\\|)[A-Za-z]+(?=\\|)"))

没有成功。 只是要记住我们应该忽略左边的字符。

2 个答案:

答案 0 :(得分:2)

执行此操作的一种方法是将J48对象从RWeka转换为party对象partykit。您只需要as.party(res),这将为您完成所有解析,并返回一个更易于使用标准化提取函数等的结构。

特别是,您可以使用有关ctree个对象的其他讨论中提供的所有建议。请参阅

我认为以下内容至少应该是您想要的部分内容:

library("partykit")
pres <- as.party(res)
partykit:::.list.rules.party(pres)
##                                                                                  2 
##                                                               "Petal.Width <= 0.6" 
##                                                                                  5 
##                     "Petal.Width > 0.6 & Petal.Width <= 1.7 & Petal.Length <= 4.9" 
##                                                                                  7 
## "Petal.Width > 0.6 & Petal.Width <= 1.7 & Petal.Length > 4.9 & Petal.Width <= 1.5" 
##                                                                                  8 
##  "Petal.Width > 0.6 & Petal.Width <= 1.7 & Petal.Length > 4.9 & Petal.Width > 1.5" 
##                                                                                  9 
##                                            "Petal.Width > 0.6 & Petal.Width > 1.7" 

更新:OP与我联系以获取相关问题,要求提供树的特定打印表示。我在这里包含我的解决方案,以防它对其他人有用。

他希望有()符号表示层次结构级别以及拆分变量的名称。一种方法是(1)提取基础数据的变量名称:

nam <- names(pres$data)

(2)将树的递归节点结构转换为平面列表(这对构造所需的字符串来说更方便):

tr <- as.list(pres$node)

(3a)初始化字符串:

str <- "("

(3b)递归地向字符串添加括号和/或变量名称:

update_str <- function(x) {
   if(is.null(x$kids)) {
     str <<- paste(str, ")")
   } else {
     str <<- paste(str, nam[x$split$varid], "(")
     for(i in x$kids) update_str(tr[[i]])
   }
}

(3c)从根节点开始调用递归:

update_str(tr[[1]])
str
## [1] "( Petal.Width ( ) Petal.Width ( Petal.Length ( ) Petal.Width ( ) ) )"

答案 1 :(得分:1)

我希望我在这里不要错过你的观点,但我认为你想要以某种方式创建和存储基于树模型的终端节点的规则。就个人而言,我发现模型树构建包(RWeka,party,partykit,rpart)缺乏使用户能够在构建模型后创建有用的规则列表。当然,当你有很少的变量和分割时,你可以解释树形图。

到目前为止,我发现的唯一简单而有力的方法(我自己使用)就是命令&#34; path.rpart&#34; rpart包的。如果您真的想使用RWeka,解决方案似乎无关紧要,但我会尝试一下:

library(rpart)

res = rpart(Species ~., data = iris)

res

# n= 150 
# 
# node), split, n, loss, yval, (yprob)
# * denotes terminal node
# 
# 1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)  
# 2) Petal.Length< 2.45 50   0 setosa (1.00000000 0.00000000 0.00000000) *
#   3) Petal.Length>=2.45 100  50 versicolor (0.00000000 0.50000000 0.50000000)  
# 6) Petal.Width< 1.75 54   5 versicolor (0.00000000 0.90740741 0.09259259) *
#   7) Petal.Width>=1.75 46   1 virginica (0.00000000 0.02173913 0.97826087) *


# capture terminal nodes
terminal_nodes = rownames(res$frame)[res$frame$var =="<leaf>"]

# print rules for the terminal nodes
path.rpart(res ,nodes=terminal_nodes)

# node number: 2 
# root
# Petal.Length< 2.45
# 
# node number: 6 
# root
# Petal.Length>=2.45
# Petal.Width< 1.75
# 
# node number: 7 
# root
# Petal.Length>=2.45
# Petal.Width>=1.75


# print above rules as list
rules = path.rpart(res ,nodes=terminal_nodes)
listed_rules = unlist(rules)
sapply(rules,"[",-1)

# $`2`
# [1] "Petal.Length< 2.45"
# 
# $`6`
# [1] "Petal.Length>=2.45" "Petal.Width< 1.75" 
# 
# $`7`
# [1] "Petal.Length>=2.45" "Petal.Width>=1.75"