【问题标题】:Running rpart over multiple subsets of a data frame在数据帧的多个子集上运行 rpart
【发布时间】:2015-07-14 07:56:24
【问题描述】:

我正在使用基于 x 个变量和数据框的 R rpart 包创建决策树:

fit<-rpart(y~x1+x2+x3+x4,data=(mydataframe),
  control=rpart.control(minsplit = 20, minbucket = 0, cp=.01))

但是,我没有使用整个数据框,而是有四五个作为因子的数据子集,假设用 x4 分隔。如何一次对所有这些因素运行决策树,而不必一次又一次地调用数据子集?

基于对 SO 的搜索,看起来 BY 或 ddply 可能是正确的选择。这是我为 ddply 尝试过的:

fit<-ddply(mydataframe, dataframe$x4, function (df)  
    rpart(y~x1+x2+x3+x4,data=(df), 
    control=rpart.control(minsplit = 20, minbucket = 0, cp=.01)))

但我得到的是:

Error in eval(expr, envir, enclos) : object 'x4value' not found

其中 x4value 是我想要拆分的变量值之一。所以我有一列值:

x4
桶名1
桶名2
桶名3
BucketName4

str(mydataframe) 表明 $x4 是一个 : 因子 w/ 8 个级别且没有符号。

此外,我在一开始就运行了 mydataframe = na.omit(dataframe) 以避免空值。

我已经解决的可能问题:

当我手动运行时,rpart 位运行良好:

mydataframe<-subset(trainData, x4=="BucketName1")

fit<-rpart(y~x1+x2+x3+x4,data=(mydataframe), 
    control=rpart.control(minsplit = 20, minbucket = 0, cp=.01))

但是每当我尝试使用 ddply 遍历所有子集时都会出错。

完整的可重现示例代码:

mydataframe<-data.frame  ( x1=sample(1:10),
                           x2=sample(1:10),
                           x3=sample(1:10),
                           x4= sample(letters[1:4], 20, replace = TRUE))
str(mydataframe)

fit<-ddply(mydataframe, mydataframe$x4, function (df)
    rpart(y~x1+x2+x3+x4,data=(df), control=rpart.control(minsplit = 20,      minbucket = 0, cp=.01)))

输出:

str(mydataframe) 'data.frame':  20 obs. of  4 variables:  $ x1: int  1 6 8 4 7 9 3 2 10 5 ...  $ x2: int  9 4 5 8 6 3 7 10 2 1 ...  $ x3: int 2 6 5 3 1 4 9 7 10 8 ...  $ x4: Factor w/ 4 levels "a","b","c","d": 4 4 3 2 3 4 3 3 1 3 ...
> fit<-ddply(mydataframe, mydataframe$x4, function (df) rpart(y~x1+x2+x3+x4,data=(df), control=rpart.control(minsplit = 20, minbucket = 0, cp=.01))) Error in eval(expr, envir, enclos) : object 'd' not found

【问题讨论】:

  • 请花时间创建一个最小的reproducible example,并带有示例输入数据。当您共享的代码中的任何地方都没有出现“x4value”时,您会收到关于“x4value”的错误,这似乎很奇怪。好像你漏掉了一些重要的东西。
  • 感谢提示,我已经添加了一些示例代码。

标签: r function plyr rpart


【解决方案1】:

如果您对 plyr 不满意,您也可以使用基本 R 函数来做到这一点。

splitData = split(mydataframe, mydataframe$x4)

getModel = function(df) {
    fit <- rpart(y~x1+x2+x3+x4+xN....,data=df, 
        control=rpart.control(minsplit = 20, minbucket = 0, cp=.01)))
    return(fit)
}

models = lapply(splitData, getModel)

您也可以使用 dplyr 而不是 plyr 来执行此操作。

mydataframe %>% group_by(x4) %>%
   do(model = getModel(.))

【讨论】:

    【解决方案2】:

    你想用你的代码做两件事:

    1. 使用 dlply 而不是 ddply,因为您需要 rpart 对象列表而不是 (?) 的数据框。如果您想显示原始数据的预测值,ddply 会很有用,因为可以将其格式化为数据框。

    2. dlply 中使用.(x4) 而不是dataframe$x4。使用后者会产生不可预知的结果。

    此外,在您的示例中,您应该指定 y 值并从 x4 之后删除 ....

    【讨论】:

    • 谢谢您,这非常有效!我最初应该指定,但我也想用 printcp(fit) 输出结果,但我得到了 Error in printcp(fit) : 'x' must be an "rpart" objectprintcp(fit)plotcp(fit)。对此部分进行故障排除的任何提示?
    • 您的结果在列表中。如果你想得到第一个结果,你可以做 print(fit[[1]]) 。您还可以创建一个自动化的 l_ply() 函数来为您完成此操作,但您的函数必须保存结果,因为这些图会相互覆盖。您还可以执行par(mfrow = c(2,2)) 之类的操作来为每个图像获取多个图。
    【解决方案3】:

    您向dplyr() .variables= 参数传递了不正确的值。您应该传递带引号的变量名、公式或变量名的字符向量。由于您正在传递 mydataframe$v4 ,因此它被强制转换为一个字符,并且它正在查找该列中的所有值,就好像它们是变量一样。

    调用应该是这样的

    fit<-ddply(mydataframe, ~x4, function (df)
        rpart(y~x1+x2+x3+x4,data=(df), control=rpart.control(minsplit = 20, minbucket = 0, cp=.01)))
    

    fit<-ddply(mydataframe, .(x4), function (df)
        rpart(y~x1+x2+x3+x4,data=(df), control=rpart.control(minsplit = 20, minbucket = 0, cp=.01)))
    

    fit<-ddply(mydataframe, "x4", function (df)
        rpart(y~x1+x2+x3+x4,data=(df), control=rpart.control(minsplit = 20,  minbucket = 0, cp=.01)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-04
      • 1970-01-01
      • 1970-01-01
      • 2021-11-08
      • 1970-01-01
      • 2020-07-07
      相关资源
      最近更新 更多