¿Cómo forzar a R a usar un nivel de factor específico como referencia en una regresión?

112

¿Cómo puedo decirle a R que use un cierto nivel como referencia si uso variables explicativas binarias en una regresión?

Solo está usando algún nivel por defecto.

lm(x ~ y + as.factor(b)) 

con b {0, 1, 2, 3, 4}. Digamos que quiero usar 3 en lugar del cero que usa R.

Matt Bannert
fuente
9
Debe realizar el paso de procesamiento de datos fuera de la fórmula / ajuste del modelo. Al crear el factor a partir de bpuede especificar el orden de los niveles usando factor(b, levels = c(3,1,2,4,5)). Sin lm()embargo, haga esto en un paso de procesamiento de datos fuera de la llamada. Mi respuesta a continuación usa la relevel()función para que pueda crear un factor y luego cambiar el nivel de referencia para que se adapte a sus necesidades.
Gavin Simpson
1
Reformulé tu pregunta. En realidad, lo que busca es cambiar el nivel de referencia, no omitir uno.
Joris Meys
gracias por reformular mi pregunta. De hecho, relevel () era lo que estaba buscando. Sin embargo, gracias por la respuesta detallada y el ejemplo. No estoy seguro de si la etiqueta de regresión lineal es un poco engañosa porque se aplica a todo tipo de regresión utilizando explicaciones ficticias ...
Matt Bannert

Respuestas:

152

Ver la relevel()función. Aquí hay un ejemplo:

set.seed(123)
x <- rnorm(100)
DF <- data.frame(x = x,
                 y = 4 + (1.5*x) + rnorm(100, sd = 2),
                 b = gl(5, 20))
head(DF)
str(DF)

m1 <- lm(y ~ x + b, data = DF)
summary(m1)

Ahora modifique el factor bin DFmediante el uso de la relevel()función:

DF <- within(DF, b <- relevel(b, ref = 3))
m2 <- lm(y ~ x + b, data = DF)
summary(m2)

Los modelos han estimado diferentes niveles de referencia.

> coef(m1)
(Intercept)           x          b2          b3          b4          b5 
  3.2903239   1.4358520   0.6296896   0.3698343   1.0357633   0.4666219 
> coef(m2)
(Intercept)           x          b1          b2          b4          b5 
 3.66015826  1.43585196 -0.36983433  0.25985529  0.66592898  0.09678759
Gavin Simpson
fuente
9
Para conservar la variable original, simplemente no use el within, pero df$bR = relevel(df$b, ref=3).
BurninLeo
1
Puede usar relevel () dentro de su fórmula, no afectaría el conjunto de datos original ...
Mehdi Zare
36

Otros han mencionado el relevelcomando que es la mejor solución si desea cambiar el nivel base para todos los análisis de sus datos (o está dispuesto a vivir con el cambio de datos).

Si no desea cambiar los datos (este es un cambio único, pero en el futuro desea el comportamiento predeterminado nuevamente), entonces puede usar una combinación de la función C(nota en mayúsculas) para establecer contrastes y la contr.treatmentsfunción con el argumento base para elegir qué nivel desea que sea la línea de base.

Por ejemplo:

lm( Sepal.Width ~ C(Species,contr.treatment(3, base=2)), data=iris )
Greg Snow
fuente
33

El relevel()comando es un método abreviado para su pregunta. Lo que hace es reordenar el factor para que el nivel de referencia sea el primero. Por lo tanto, reordenar los niveles de los factores también tendrá el mismo efecto pero le dará más control. Quizás quisieras tener niveles 3,4,0,1,2. En ese caso...

bFactor <- factor(b, levels = c(3,4,0,1,2))

Prefiero este método porque es más fácil para mí ver en mi código no solo cuál era la referencia, sino también la posición de los otros valores (en lugar de tener que mirar los resultados para eso).

NOTA: NO lo convierta en un factor ordenado. Un factor con un orden específico y un factor ordenado no son lo mismo. lm()puede comenzar a pensar que desea contrastes polinomiales si lo hace.

Juan
fuente
2
Contrastes polinomiales, no una regresión polinomial.
hadley
¿Hay alguna forma de establecer el nivel de referencia al mismo tiempo que define el factor, en lugar de en una llamada posterior a relevel?
David Bruce Borenstein
31

Sé que esta es una pregunta antigua, pero tuve un problema similar y descubrí que:

lm(x ~ y + relevel(b, ref = "3")) 

hace exactamente lo que pediste.

Yan Alperovych
fuente
3
¡Esta fue una gran ayuda! La única solución que incluía una forma de hacerlo dentro del comando lm () que era exactamente lo que necesitaba. ¡Gracias!
cparmstrong
3
Esta es una forma muy flexible de trabajar con factores. Me gusta el hecho de que puedo combinarlo as.factor()si es necesario, por ejemplo, usando...+relevel(as.factor(mycol), ref = "myref")+...
Peter
12

También puede etiquetar manualmente la columna con un contrastsatributo, que parece ser respetado por las funciones de regresión:

contrasts(df$factorcol) <- contr.treatment(levels(df$factorcol),
   base=which(levels(df$factorcol) == 'RefLevel'))
Harlan
fuente
1

Para aquellos que buscan una versión dplyr / tidyverse. Basándose en la solución de Gavin Simpson:

# Create DF
set.seed(123)
x <- rnorm(100)
DF <- data.frame(x = x,
                 y = 4 + (1.5*x) + rnorm(100, sd = 2),
                 b = gl(5, 20))

# Change reference level
DF = DF %>% mutate(b = relevel(b, 3))

m2 <- lm(y ~ x + b, data = DF)
summary(m2)
Gorka
fuente
Estoy confundido por qué pusiste "Si la variable es un factor" donde lo hiciste ... esto es necesario si usas relevel()oforcats::fct_relevel()
Gregor Thomas
¡Tienes razón, gracias! Agregué "también puedes usar", porque, afaik, fct_relevel solo funciona con factores.
Gorka
2
relevelsolo funciona con factores. fct_relevelsolo funciona con factores. No hay ninguna diferencia entre las funciones excepto el nombre, AFAIK. Decir "Si la variable es un factor que también puedes usar fct_relevel" implica que si la variable no es un factor que podrías usar relevel, pero eso no es cierto.
Gregor Thomas