Как использовать функции PreProcess, когда некоторые из них являются факторами?
Мой вопрос связан с этим относительно категориальных данных (факторов в терминах R) при использовании пакета Caret. Я понимаю из связанного сообщения, что если вы используете "интерфейс формулы", некоторые функции могут быть факторами, и обучение будет работать нормально. Мой вопрос: как я могу масштабировать данные с помощью функции 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)
Спасибо.
Ответы
Ответ 1
Это действительно та же проблема, что и сообщение, на которое вы ссылаетесь. 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
на этом объекте.
btw make preProcess
игнорировать нечисловые данные в моем списке "делать", но это может привести к ошибкам для людей, не обращающих внимания.
Max
Ответ 2
Вот быстрый способ исключить факторы или что бы вы хотели от рассмотрения:
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
.