当一些特征是因子时,如何进行预处理?

14

我关于这个问题与使用Caret软件包时涉及到分类数据(R术语中的因子)。 我从链接的帖子中了解到,如果您使用“公式界面”,一些特征可以是因子,并且培训将正常进行。 我的问题是如何使用preProcess()函数对数据进行缩放? 如果我尝试对某些列作为因子的数据框进行此操作,则会收到此错误消息:

Error in preProcess.default(etitanic, method = c("center", "scale")) : 
  all columns of x must be numeric

看这里一些示例代码:

library(earth)
data(etitanic)

a <- preProcess(etitanic, method=c("center", "scale"))
b <- predict(etitanic, a)

谢谢。


可能是 https://dev59.com/wJffa4cB1Zd3GeqP3SGp 的重复问题 - Holger Brandl
2个回答

22

这实际上是与您链接到的帖子完全相同的问题。 preProcess 仅适用于数字数据,而您有:

> str(etitanic)
'data.frame':   1046 obs. of  6 variables:
 $ pclass  : Factor w/ 3 levels "1st","2nd","3rd": 1 1 1 1 1 1 1 1 1 1 ...
 $ survived: int  1 1 0 0 0 1 1 0 1 0 ...
 $ sex     : Factor w/ 2 levels "female","male": 1 2 1 2 1 2 1 2 1 2 ...
 $ age     : num  29 0.917 2 30 25 ...
 $ sibsp   : int  0 1 1 1 1 0 1 0 2 0 ...
 $ parch   : int  0 2 2 2 2 0 0 0 0 0 ...

你不能直接对于pclass或者sex进行居中和缩放,因此它们需要被转换为哑变量。你可以使用model.matrix或caret的dummyVars进行转换:

 > new <- model.matrix(survived ~ . - 1, data = etitanic)
 > colnames(new)
 [1] "pclass1st" "pclass2nd" "pclass3rd" "sexmale"   "age"      
 [6] "sibsp"     "parch"  

-1消除截距。现在,您可以在此对象上运行preProcess

顺便说一下,让preProcess忽略非数字数据是我的“待办事项”清单上,但这可能会导致不注意的人出错。

Max


1
我认为我们只需要两个变量来表示pclass。(可以是“pclass1st,pclass2nd”或“pclass2nd,pclass3rd”或“pclass3rd,pclass1st”)。就像在性别变量的情况下,我们只考虑了性别男性并丢弃了性别女性一样。如果不够,请纠正我。 - Sandeep
@topepo,我认为下面的答案忽略了待办事项清单。我建议为那些不注意的人添加一些警告。 - toto_tico

8
这里有一种快速的方法可以排除因素或其他你不想考虑的内容:
set.seed(1)
N <- 20
dat <- data.frame( 
    x = factor(sample(LETTERS[1:5],N,replace=TRUE)),
    y = rnorm(N,5,12),
    z = rnorm(N,-5,17) + runif(N,2,12)
)

#' Function which wraps preProcess to exclude factors from the model.matrix
ppWrapper <- function( x, excludeClasses=c("factor"), ... ) {
    whichToExclude <- sapply( x, function(y) any(sapply(excludeClasses, function(excludeClass) is(y,excludeClass) )) )
    processedMat <- predict( preProcess( x[!whichToExclude], ...), newdata=x[!whichToExclude] )
    x[!whichToExclude] <- processedMat
    x
}

> ppWrapper(dat)
   x          y           z
1  C  1.6173595 -0.44054795
2  A -0.2933705 -1.98856921
3  C  1.2177384  0.65420288
4  D -0.8710374  0.62409408
5  D -0.4504202 -0.34048640
6  D -0.6943283  0.24236671
7  E  0.7778192  0.91606677
8  D  0.2184563 -0.44935163
9  C -0.3611408  0.26075970
10 B -0.7066441 -0.23046073
11 D -1.5154339 -0.75549761
12 D  0.4504825  0.38552988
13 B  1.5692675  0.04093040
14 C  0.4127541  0.13161807
15 D  0.5426321  1.09527418
16 B -2.1040322 -0.04544407
17 C  0.6928574  1.12090541
18 B  0.3580960  1.91446230
19 E  0.3619967 -0.89018040
20 A -1.2230522 -2.24567237

您可以将任何内容传递到ppWrapper中,并将其传递给preProcess


好答案!我认为你应该使用给出的示例(而不是可能会令人困惑的人工示例)。基本上,library(earth); data(etitanic); ppWrapper(etitanic) - toto_tico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接