Todos los niveles de un factor en una matriz modelo en R

Tengo un data.frame consta de variables numéricas y de factor como se ve a continuación.

 testFrame <- data.frame(First=sample(1:10, 20, replace=T), Second=sample(1:20, 20, replace=T), Third=sample(1:10, 20, replace=T), Fourth=rep(c("Alice","Bob","Charlie","David"), 5), Fifth=rep(c("Edward","Frank","Georgia","Hank","Isaac"),4)) 

Quiero construir una matrix que asigne variables ficticias al factor y deje solo las variables numéricas.

 model.matrix(~ First + Second + Third + Fourth + Fifth, data=testFrame) 

Como se esperaba al ejecutar lm esto deja fuera un nivel de cada factor como nivel de referencia. Sin embargo, quiero construir una matrix con una variable ficticia / indicadora para cada nivel de todos los factores. Estoy construyendo esta matriz para glmnet así que no estoy preocupado por la multicolinealidad.

¿Hay alguna manera de tener model.matrix crear el dummy para cada nivel del factor?

Debe restablecer los contrasts para las variables de factor:

 model.matrix(~ Fourth + Fifth, data=testFrame, contrasts.arg=list(Fourth=contrasts(testFrame$Fourth, contrasts=F), Fifth=contrasts(testFrame$Fifth, contrasts=F))) 

o, con un poco menos de tipeo y sin los nombres propios:

 model.matrix(~ Fourth + Fifth, data=testFrame, contrasts.arg=list(Fourth=diag(nlevels(testFrame$Fourth)), Fifth=diag(nlevels(testFrame$Fifth)))) 

(Intentando redimirme …) En respuesta al comentario de Jared sobre la respuesta de @Fabians sobre la automatización, tenga en cuenta que todo lo que necesita proporcionar es una lista con nombre de matrices de contraste. contrasts() toma un vector / factor y produce la matriz de contrastes a partir de él. Para esto, podemos usar lapply() para ejecutar contrasts() en cada factor en nuestro conjunto de datos, por ejemplo, para el ejemplo testFrame proporcionado:

 > lapply(testFrame[,4:5], contrasts, contrasts = FALSE) $Fourth Alice Bob Charlie David Alice 1 0 0 0 Bob 0 1 0 0 Charlie 0 0 1 0 David 0 0 0 1 $Fifth Edward Frank Georgia Hank Isaac Edward 1 0 0 0 0 Frank 0 1 0 0 0 Georgia 0 0 1 0 0 Hank 0 0 0 1 0 Isaac 0 0 0 0 1 

Que las ranuras muy bien en @fabianos responden:

 model.matrix(~ ., data=testFrame, contrasts.arg = lapply(testFrame[,4:5], contrasts, contrasts=FALSE)) 

dummyVars de caret también podría ser utilizado. http://caret.r-forge.r-project.org/preprocess.html

caret implementó una buena función dummyVars para lograr esto con 2 líneas:

library(caret) dmy <- dummyVars(" ~ .", data = testFrame) testFrame2 <- data.frame(predict(dmy, newdata = testFrame))

Verificando las columnas finales:

 colnames(testFrame2) "First" "Second" "Third" "Fourth.Alice" "Fourth.Bob" "Fourth.Charlie" "Fourth.David" "Fifth.Edward" "Fifth.Frank" "Fifth.Georgia" "Fifth.Hank" "Fifth.Isaac" 

El mejor punto aquí es obtener el dataframe original, más las variables ficticias que excluyeron las originales usadas para la transformación.

Más información: http://amunategui.github.io/dummyVar-Walkthrough/

De acuerdo. Acabo de leer lo anterior y ponerlo todo junto. Supongamos que quiere la matriz, por ejemplo, ‘X.factores’ que se multiplica por su vector de coeficientes para obtener su predictor lineal. Todavía hay un par de pasos adicionales:

 X.factors = model.matrix( ~ ., data=X, contrasts.arg = lapply(data.frame(X[,sapply(data.frame(X), is.factor)]), contrasts, contrasts = FALSE)) 

(Tenga en cuenta que debe volver a X [*] en un dataframe en caso de que tenga solo una columna de factores).

Entonces di que obtienes algo como esto:

 attr(X.factors,"assign") [1] 0 1 **2** 2 **3** 3 3 **4** 4 4 5 6 7 8 9 10 #emphasis added 

Queremos deshacernos de los niveles de referencia ** ‘d de cada factor

 att = attr(X.factors,"assign") factor.columns = unique(att[duplicated(att)]) unwanted.columns = match(factor.columns,att) X.factors = X.factors[,-unwanted.columns] X.factors = (data.matrix(X.factors)) 

Usando el paquete R ‘CatEncoders’

 library(CatEncoders) testFrame <- data.frame(First=sample(1:10, 20, replace=T), Second=sample(1:20, 20, replace=T), Third=sample(1:10, 20, replace=T), Fourth=rep(c("Alice","Bob","Charlie","David"), 5), Fifth=rep(c("Edward","Frank","Georgia","Hank","Isaac"),4)) fit <- OneHotEncoder.fit(testFrame) z <- transform(fit,testFrame,sparse=TRUE) # give the sparse output z <- transform(fit,testFrame,sparse=FALSE) # give the dense output 
 model.matrix(~ First + Second + Third + Fourth + Fifth - 1, data=testFrame) 

o

 model.matrix(~ First + Second + Third + Fourth + Fifth + 0, data=testFrame) 

debería ser el más sencillo

F

Actualmente estoy aprendiendo el modelo Lasso y glmnet::cv.glmnet() , model.matrix() y Matrix::sparse.model.matrix() (para matriz de altas dimensiones, usando model.matrix nuestro tiempo como lo sugiere el autor de glmnet .).

Solo compartir allí tiene una encoding ordenada para obtener la misma respuesta que @fabians y la respuesta de @Gavin. Mientras tanto, @ asdf123 introdujo otra library('CatEncoders') paquetes library('CatEncoders') también.

 > require('useful') > # always use all levels > build.x(First ~ Second + Fourth + Fifth, data = testFrame, contrasts = FALSE) > > # just use all levels for Fourth > build.x(First ~ Second + Fourth + Fifth, data = testFrame, contrasts = c(Fourth = FALSE, Fifth = TRUE)) 

Fuente: R para todos: Análisis avanzado y gráficos (página273)

    Intereting Posts