R中的闭包,在函数内调用函数,递归函数

时间:2016-01-25 16:16:30

标签: r function closures party

我是R的新手,我正在使用party:ctree库尝试分类决策树。一切似乎都很好。我得到了预期的结果和一个很好描述的情节。

现在,如果我想从拟合的摘要中提取结果,我将遍历每个节点并提取信息。幸运的是,这已经由@baydoganm here编写。我想扩展此代码并将结果写入dataframe而不是打印它。

可重现的代码:

library(party)
 ct <- ctree(Species ~ ., data = iris)

   traverse <- function(treenode){
        if(treenode$terminal){
           bas=paste(treenode$nodeID,treenode$prediction)
         print(bas) #here the results are printed
         return(0)
                } 

 traverse(treenode$left)
 traverse(treenode$right)
  }

 traverse(ct@tree) #function call

这很好用,我在控制台上获得输出。现在,如果我想将结果写入数据框,我将遇到问题。

到目前为止我尝试过:尝试使用可变闭包()写入列表。但不知道如何让它发挥作用。

l <- list()
count = 0
traverse1 <- function(treenode,l){

if((treenode$terminal == T)){
    count <<- count + 1
    print(count)
    node = c(treenode$nodeID)
    pred = c(treenode$prediction)
    l[[count]] <- data.frame(node,pred) #write results in the dataframe    
  } 

  traverse1(treenode$left,l)
  traverse1(treenode$right,l)

}
test <- traverse1(ct@tree,l)# function call

我只获得上次调用函数的结果,其余为null

2 个答案:

答案 0 :(得分:2)

智能方式:使用assign()在全球环境中撰写:

require(party) 
ct <- ctree(Species ~ ., data = iris)

tt <- NULL

traverse <- function(treenode){
  if(treenode$terminal){
    bas=paste(treenode$nodeID,treenode$prediction)
    assign("tt", c(tt, bas), envir = .GlobalEnv)
    print(bas) #here the results are printed
    return(0)
  } 

  traverse(treenode$left)
  traverse(treenode$right)
}

traverse(ct@tree) #function call

data.frame(node.id = unlist(lapply(str_split(tt, " "), function(x) x[[1]]))
       , prediction = unlist(lapply(str_split(tt, " "), function(x) x[[2]])))

脏话:使用sink()保存您的打印输出。

sink(file = "test.csv", append = T)
traverse(ct@tree) #function call
sink()

tt <- read.csv("test.csv", header = F)

答案 1 :(得分:2)

如果您使用ctree()软件包中新的改进的partykit实施方案,那么它在fitted组件中包含您需要的所有信息:

library("partykit")
ct <- ctree(Species ~ ., data = iris)
head(fitted(ct))
##   (fitted) (weights) (response)
## 1        2         1     setosa
## 2        2         1     setosa
## 3        2         1     setosa
## 4        2         1     setosa
## 5        2         1     setosa
## 6        2         1     setosa

因此,对于分类树,您可以使用xtabs()(或table())轻松构建响应的绝对频率表。对于回归树,tapply()可以很容易地用于获取资金,中位数等。

在这种情况下,让我们以表格形式查看绝对频率和相对频率:

tab <- xtabs(~ `(fitted)` + `(response)`, data = fitted(ct))
tab
##         (response)
## (fitted) setosa versicolor virginica
##        2     50          0         0
##        5      0         45         1
##        6      0          4         4
##        7      0          1        45
ptab <- prop.table(tab, 1)
ptab
##         (response)
## (fitted)     setosa versicolor  virginica
##        2 1.00000000 0.00000000 0.00000000
##        5 0.00000000 0.97826087 0.02173913
##        6 0.00000000 0.50000000 0.50000000
##        7 0.00000000 0.02173913 0.97826087

获取频率表tab的另一种途径是:table(predict(ct, type = "node"), iris$Species)

如果你想将这些中的任何一个变成一个数据框,那么as.data.frame()就可以正常工作(可能加上一些重新标记的变量......):

as.data.frame(ptab)
##    X.fitted. X.response.       Freq
## 1          2      setosa 1.00000000
## 2          5      setosa 0.00000000
## 3          6      setosa 0.00000000
## 4          7      setosa 0.00000000
## 5          2  versicolor 0.00000000
## 6          5  versicolor 0.97826087
## 7          6  versicolor 0.50000000
## 8          7  versicolor 0.02173913
## 9          2   virginica 0.00000000
## 10         5   virginica 0.02173913
## 11         6   virginica 0.50000000
## 12         7   virginica 0.97826087