La caída de la variable en la fórmula lm aún desencadena un error de contraste

9

Estoy tratando de ejecutar lm () solo en un subconjunto de mis datos y me encuentro con un problema.

dt = data.table(y = rnorm(100), x1 = rnorm(100), x2 = rnorm(100), x3 = as.factor(c(rep('men',50), rep('women',50)))) # sample data

lm( y ~ ., dt) # Use all x: Works
lm( y ~ ., dt[x3 == 'men']) # Use all x, limit to men: doesn't work (as expected)

Lo anterior no funciona porque el conjunto de datos ahora solo tiene hombres y, por lo tanto, no podemos incluir x3, la variable de género, en el modelo. PERO...

lm( y ~ . -x3, dt[x3 == 'men']) # Exclude x3, limit to men: STILL doesn't work
lm( y ~ x1 + x2, dt[x3 == 'men']) # Exclude x3, with different notation: works great

Este es un problema con la notación de "signo menos" en la fórmula? Por favor aconséjame. Nota: Por supuesto que puedo hacerlo de otra manera; por ejemplo, podría excluir las variables antes de ponerlas en lm (). Pero estoy enseñando una clase sobre estas cosas, y no quiero confundir a los estudiantes, ya que les dije que pueden excluir variables usando un signo menos en la fórmula.

Zhaochen He
fuente
3
Es interesante que tanto model.matrix(y ~ . - x3, data = dt[x3 == "men"])y model.matrix(y ~ x1 + x2, data = dt[x3 == "men"])trabajo ( lmllamadas model.matrixinternas). La única diferencia entre ambas matrices modelo es un "contrasts"atributo (que todavía contiene x3) y que se recoge más adelante dentro de la lmrutina, lo que probablemente cause el error que está viendo. Entonces, creo que el problema tiene que ver con cómo model.matrixcrea y almacena la matriz de diseño al eliminar términos.
Maurits Evers
Estaba tratando de "expandir" .para obtener una fórmula simplificada, terms(y ~ . -x3, data=dt, simplify=TRUE)pero curiosamente aún conserva x3el atributo de variables que se disparalm
MrFlick
1
@MrFlick: parece que la neg.out=opción no implementada en R podría estar relacionada. De los archivos de ayuda S para terms, dónde neg.out=se implementa: marca que controla el tratamiento de los términos que ingresan con el signo "-". Si es VERDADERO, los términos serán verificados para cancelación y de otra manera ignorados. Si es FALSO, los términos negativos se conservarán (con orden negativo).
thelatemail
1
@MauritsEvers: lmllamadas model.matrixen una versión modificada de los datos. En el principio, lmcompone y evalúa la siguiente expresión: mf <- stats::model.frame( y ~ . -x3, dt[x3=="men"], drop.unused.levels=TRUE ). Esto hace x3que se convierta en un factor de un solo nivel. model.matrix()luego se llama mf, no los datos originales, lo que resulta en el error que estamos observando.
Artem Sokolov

Respuestas:

2

El error que está recibiendo es porque x3 está en el modelo con un solo valor = "men"(vea el comentario a continuación de @Artem Sokolov)

Una forma de resolverlo es subconjunto de antemano:

dt = data.table(y = rnorm(100), x1 = rnorm(100), x2 = rnorm(100), x3 = as.factor(c(rep('men',50), rep('women',50)))) # sample data

dmen<-dt[x3 == 'men'] # create a new subsetted dataset with just men

lm( y ~ ., dmen[,-"x3"]) # now drop the x3 column from the dataset (just for the model)

O puede hacer ambas cosas en el mismo paso:

lm( y ~ ., dt[x3 == 'men',-"x3"])
Dylan_Gomes
fuente
En general, esta es una buena solución. Una cosa para corregir es que -x3en una fórmula no hace lmpensar que estás tratando de restar la columna. El "no utilice x3 en el modelo de" intención se comunica correctamente, pero el problema es que lmlas llamadas model.frame( ..., drop.unused.levels=TRUE )causando x3a convertirse en un factor de un solo nivel, lo que lleva a problemas aguas abajo en model.matrix().
Artem Sokolov
Gracias por aclarar Artem Sokolov, he tomado esa explicación incorrecta de mi respuesta.
Dylan_Gomes