transformar - Todos los niveles de un factor en una matriz modelo en R
tablas en r (8)
(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))
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?
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 codificación 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)
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 marco de datos 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))
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))))
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
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 marco de datos 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/
dummyVars
de caret
también podría ser utilizado. http://caret.r-forge.r-project.org/preprocess.html
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