【问题标题】:Dropping column using tidyverse and base R - the difference使用 tidyverse 和 base R 删除列 - 区别
【发布时间】:2018-04-28 09:37:28
【问题描述】:

在尝试适应 randomForest 并使用 select 按名称选择/删除数据框列时,我最终遇到了一个奇怪的行为:

library(MASS)
library(dplyr)
library(purrr)
library(randomForest)

train = base::sample(1:nrow(Boston), nrow(Boston)/2)
glimpse(Boston)
p <- ncol(Boston) - 1
ps <- 1:p
map_dbl(ps, ~mean(randomForest(x = select(Boston[train,], -medv), 
                           y = select(Boston[train,], medv), 
                           xtest = select(Boston[-train,], -medv),
                           ytest = select(Boston[-train,], medv),
                           mtry = .x, ntree = 500)$test$mse)) 

这最终出现以下错误:

randomForest.default(x = select(Boston[train, ], -medv), y = select(Boston[train, : 响应长度必须与预测变量相同 另外:警告信息: 在 randomForest.default(x = select(Boston[train, ], -medv), y = select(Boston[train, : 响应具有五个或更少的唯一值。您确定要进行回归吗?

但是,当我用基数 R 定义 x、y、xtest、ytest 时,公式有效:

map_dbl(ps, ~mean(randomForest(x = Boston[train, -14], 
                           y = Boston[train, 14], 
                           xtest = Boston[-train, -14],
                           ytest = Boston[train, 14],
                           mtry = .x, ntree = 500)$test$mse)) 

[1] 119.9225 132.5212 136.7131 139.7398 142.9167 144.2151 145.0587 146.9056 148.7087 148.1903 150.3910 [12] 151.5579 151.2323

所以我检查了这两种不同的子集化数据集的方法是否给出了相同的结果......然后做。

all(select(Boston[train,], -medv) == Boston[train, -14])
all(select(Boston[train,], medv) == Boston[train, 14])
all(select(Boston[-train,], -medv) == Boston[-train, -14])
all(select(Boston[-train,], medv) == Boston[-train, 14])

所有这些结果都是TRUE。为什么使用select 的第一个子集方法最终会在randomForest 模型中出现错误?使用他们的名字删除列的另一种方法是什么? (类似于Boston[,-"medv"] 显然不起作用。

【问题讨论】:

  • 确保您使用的是来自dplyr 包的select 函数,而不是来自MASS 包的函数。
  • 你确定有一个名为“train”的变量吗?我运行您的代码并收到以下错误:[.data.frame(Boston, train, -14) 中的错误:找不到对象“火车”
  • @ScipioneSarlo,用train定义编辑,@www 是的,我用dpyr::select检查过

标签: r dplyr


【解决方案1】:

问题在于randomForest 中的 y。它们需要是向量而不是 data.frames。

如果你使用dplyr::select,它总是返回一个data.frame。

str(dplyr::select(Boston, medv)
'data.frame':   506 obs. of  1 variable:
 $ medv: num  24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...

与通过基数 R 选择单个列相比

str(Boston[, 14])
 num [1:506] 24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...

要在选择 1 列时获得与 dplyr 相同的结果,您需要在 data.frame 单列选择中使用 drop = FALSE。

str(Boston[, 14, drop = FALSE])
'data.frame':   506 obs. of  1 variable:
 $ medv: num  24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...

为了让您的代码正确,您可以使用purrr 中的as_vector 将包含medv 的data.frame 强制转换为向量。

map_dbl(ps, ~mean(randomForest(x = dplyr::select(Boston[train,], -medv), 
                               y = as_vector(dplyr::select(Boston[train,], medv)), 
                               xtest = dplyr::select(Boston[-train,], -medv),
                               ytest = as_vector(dplyr::select(Boston[-train,], medv)),
                               mtry = .x, ntree = 500)$test$mse)) 



[1] 22.36214 15.52031 13.24707 12.22685 12.32809 11.82220 11.91149 11.65336 12.05399 12.16599 12.63174 12.79196 12.41167

【讨论】:

    【解决方案2】:

    运行下面的代码,我们可以看到第二行和第四行其实是不一样的。

    identical(select(Boston[train,], -medv), Boston[train, -14])
    # [1] TRUE
    identical(select(Boston[train,], medv), Boston[train, 14])
    # [1] FALSE
    identical(select(Boston[-train,], -medv), Boston[-train, -14])
    # [1] TRUE
    identical(select(Boston[-train,], medv), Boston[-train, 14])
    # [1] FALSE
    

    关键是select(Boston[train,], medv)返回一个数据框,而Boston[train, 14]返回一个向量。看起来我们需要为 yytest 参数提供一个向量。

    因此,以下将起作用,因为来自 包的 pull 返回一个向量。

    map_dbl(ps, ~mean(randomForest(x = select(Boston[train,], -medv), 
                                   y = pull(Boston[train,], medv), 
                                   xtest = select(Boston[-train,], -medv),
                                   ytest = pull(Boston[-train,], medv),
                                   mtry = .x, ntree = 500)$test$mse))
    

    我们也可以使用 包中的pluck

    map_dbl(ps, ~mean(randomForest(x = select(Boston[train,], -medv), 
                                   y = pluck(Boston[train,], "medv"), 
                                   xtest = select(Boston[-train,], -medv),
                                   ytest = pluck(Boston[-train,], "medv"),
                                   mtry = .x, ntree = 500)$test$mse))
    

    最后一件事,我认为对于您的第二个示例,ytest 参数应该是 Boston[-train, 14],您缺少减号。

    【讨论】:

      猜你喜欢
      • 2019-11-06
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 2010-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多