Voy a hacer una serie de entradas sobre codificación de variables categóricas, mi idea es pasar desde la codificación parcial (OneHot Encoders para los modernos), hasta utilizar embeddings. Vamos al lío.
Tradicionalmente, si tenemos una variable categórica con 5 niveles se codifica en tantas variables cero uno como niveles menos uno, puesto que uno de los niveles se toma como referencia y se codifica con todo 0’s en las varaibles indicadoras.
Veamos un ejemplo con el conjunto de datos Prestige del paquete car
en R.
library(car)
## Loading required package: carData
datos <- Prestige
DT::datatable(datos)
Tenemos la variable type
que es categórica, con 3 categorías
table(datos$type)
##
## bc prof wc
## 44 31 23
Por defecto R usa la codificación parcial tomando como nivel de referencia el primero.
Aquí vemos como sería la codificación
contrasts(datos$type)
## prof wc
## bc 0 0
## prof 1 0
## wc 0 1
Pero lo podemos cambiar
datos$type <- relevel(datos$type, ref="prof")
contrasts(datos$type)
## bc wc
## prof 0 0
## bc 1 0
## wc 0 1
Otros tipos de codificación similares, son helmert
o sum
(deviation coding o sum to zero)
contrasts(datos$type) <- "contr.helmert"
contrasts(datos$type)
## [,1] [,2]
## prof -1 -1
## bc 1 -1
## wc 0 2
contrasts(datos$type) <- "contr.sum"
contrasts(datos$type)
## [,1] [,2]
## prof 1 0
## bc 0 1
## wc -1 -1
Este tipo de codificación viene del análisis ANOVA.
Volvamos al contraste por defecto
contrasts(datos$type) <- "contr.treatment"
contrasts(datos$type)
## bc wc
## prof 0 0
## bc 1 0
## wc 0 1
Este tipo de codificación es el que hace que por ejemplo en un modelo lineal tengamos tantos coeficientes como niveles del factor menos 1.
foo_model <- lm(income ~ type, data = datos)
summary(foo_model)
##
## Call:
## lm(formula = income ~ type, data = datos)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5945.5 -2003.3 -466.2 1536.9 15319.5
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 10559.5 621.7 16.986 < 2e-16 ***
## typebc -5185.3 811.6 -6.389 6.16e-09 ***
## typewc -5507.1 952.5 -5.782 9.40e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3461 on 95 degrees of freedom
## (4 observations deleted due to missingness)
## Multiple R-squared: 0.3437, Adjusted R-squared: 0.3299
## F-statistic: 24.87 on 2 and 95 DF, p-value: 2.057e-09
Y de este modelo tenemos que el intercept se corresponde con la media del salario de proof
, el intercept + typebc es la media de salario de bc
y el intercept + typewc es la media de salario de wc
tapply(datos$income, datos$type, mean)
## prof bc wc
## 10559.452 5374.136 5052.304
Si quitamos el intercept tenemos la media directamente en el modelo.
foo_model_2 <- lm(income ~ type - 1 , data = datos)
summary(foo_model_2)
##
## Call:
## lm(formula = income ~ type - 1, data = datos)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5945.5 -2003.3 -466.2 1536.9 15319.5
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## typeprof 10559.5 621.7 16.99 < 2e-16 ***
## typebc 5374.1 521.8 10.30 < 2e-16 ***
## typewc 5052.3 721.7 7.00 3.6e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3461 on 95 degrees of freedom
## (4 observations deleted due to missingness)
## Multiple R-squared: 0.8236, Adjusted R-squared: 0.818
## F-statistic: 147.9 on 3 and 95 DF, p-value: < 2.2e-16
En próximas entradas contaré algo de la codificación por impacto o la que se deriva de usar un modelo mixto.
comments powered by Disqus