【问题标题】:R put multiple randomForest objects into a vectorR将多个randomForest对象放入一个向量中
【发布时间】:2011-12-10 14:04:10
【问题描述】:

我很好奇 R 是否能够将对象放入向量/列表/数组/等中。我正在使用 randomforest 包来处理大量数据的子集,并希望将每个版本存储在一个列表中。应该是这样的:

answers <- c()
for(i in 1:10){
x <- round((1/i), 3)
answers <- (rbind(answers, x))
}

理想情况下,我想做这样的事情:

answers <- c()
for(i in 1:10){
RF <- randomForest(training, training$data1, sampsize=c(100), do.trace=TRUE, importance=TRUE, ntree=50,,forest=TRUE)
answers <- (rbind(answers, RF))
}

这种方法可行,但这是单个 RF 对象的输出:

> RF 

Call:
 randomForest(x = training, y = training$data1, ntree = 50, sampsize = c(100), importance = TRUE, do.trace = TRUE,      forest = TRUE) 
               Type of random forest: regression
                     Number of trees: 10
No. of variables tried at each split: 2

          Mean of squared residuals: 0.05343956
                    % Var explained: 14.32

虽然这是“答案”列表的输出:

> answers 
   call       type         predicted      mse        rsq        oob.times      importance importanceSD
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
RF Expression "regression" Numeric,150000 Numeric,10 Numeric,10 Integer,150000 Numeric,16 Numeric,8   
   localImportance proximity ntree mtry forest  coefs y              test inbag
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 
RF NULL            NULL      10    2    List,11 NULL  Integer,150000 NULL NULL 

有谁知道如何存储所有 RF 对象或调用它们以使存储的信息与单个 RF 对象相同?感谢您的建议。

【问题讨论】:

    标签: r list random-forest


    【解决方案1】:

    不要一次增长向量或列出一个元素。预先分配它们并将对象分配给特定部分:

    answers <- vector("list",10)
    for (i in 1:10){
        answers[[i]] <- randomForest(training, training$data1, sampsize=c(100), 
                                     do.trace=TRUE, importance=TRUE, ntree=50,
                                     forest=TRUE)
    }
    

    附带说明,rbinding 向量不会创建另一个向量或列表;如果您在第一个示例中检查输出,您会发现它是一个包含一列的矩阵。这解释了您在尝试将rbindrandomForest 对象放在一起时观察到的奇怪行为。

    【讨论】:

    • 为什么我们不能动态地增长它们?这是 R 的限制吗?
    • 动态增长列表和数组通常被认为是一个坏主意,因为在大多数语言中,它比仅仅预先分配一个空数组和分配要慢。也就是说,它已经开始成为一种错误的宗教教条。如果您正在编写只会执行一次的代码并且您正在使用小型数组(例如只有 10 个元素的 OP),那么这是一个很小的微优化,您甚至可能不会注意到其中的差异,并且应该改用最易读的东西。
    【解决方案2】:

    使用以下命令初始化列表:

    mylist <- vector("list")  # technically all objects in R are vectors
    

    添加到它:

    new_element <- 5
    mylist <- c(mylist, new_element)
    

    @joran 关于预分配的建议在列表很大时是相关的,但在列表很小时并不完全必要。您还可以访问您在原始代码中构建的矩阵。它看起来有点奇怪,但信息都在那里。例如,该列表矩阵的第一个元素可以通过以下方式恢复:

    answers[1, ]
    

    【讨论】:

      【解决方案3】:

      使用lapply:

      lapply(1:10,function(i) randomForest(<your parameters>))
      

      你会得到一个随机森林对象的列表;然后,您可以使用[[]] 运算符访问其中的第 i 个。

      【讨论】:

        【解决方案4】:

        其他答案提供了将随机森林对象存储在 list 中的解决方案,但它们没有解释它们为什么起作用。

        正如@42- 所暗示的,这不是解决这里问题的预分配步骤。

        真正的问题是randomForest 对象本质上是list(检查is.list(randomForest(...))。当你写这样的语句时:

        list_of_rf = c()                                       # ... or list_of_rf = NULL
        list_of_rf = rbind(list_of_rf, randomForest(...))      # ... or list_of_rf = c(list_of_rf, randomForest(...))
        

        您实际上是在要求将一个空对象与一个列表连接起来。此语句不会生成长度为 1 的列表(随机森林模型),而是生成包含所有随机森林模型组件的列表!您可以通过在 R 控制台中输入来验证这一点:

        > 长度(list_of_rf)

        [1] 19

        有几种方法可以强制 R 执行您想要的操作:

        1. 列表中的显式做作(参见@joran 的回答,虽然不需要预先分配):

          list_of_rf = NULL
          list_of_rf[[1]] = randomForest(...)
          
        2. lapply(或类似的)建立列表(cf @mbq 答案):

          list_of_rf = lapply(..., function(i) randomForest(...))
          
        3. 将随机森林封装在一个列表中,在串联过程中会进行简化:

          list_of_rf = NULL
          list_of_rf = c(list_of_rf, list(randomForest(...)))
          

        最后,如果你犯了一个错误并取消了你的 randomForest 模型,这个模型需要 10 个小时才能计算出来,别担心,你仍然可以按如下方式恢复它:

        list_of_rf = NULL
        list_of_rf = c(list_of_rf, randomForest(...)) # oups, mistake
        rf = as.vector(list_of_rf)[1:19]
        class(rf) = 'randomForest'
        

        【讨论】:

          猜你喜欢
          • 2016-08-20
          • 1970-01-01
          • 2014-08-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-31
          • 1970-01-01
          相关资源
          最近更新 更多