2

如果您运行以下命令:

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]+(?=\\|)"))

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

4

2 回答 2

2

执行此操作的一种方法是将J48对象从转换为来自RWekaparty对象partykit。您只需要 as 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 ( ) ) )"
于 2015-08-27T14:16:12.797 回答
1

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

到目前为止,我发现的唯一简单而可靠的方法(我自己使用)是 rpart 包的命令“path.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" 
于 2015-08-23T18:23:20.323 回答