Soltar variável na fórmula lm ainda aciona erro de contraste

9

Estou tentando executar lm () em apenas um subconjunto dos meus dados e encontrando um 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)

O exemplo acima não funciona porque o conjunto de dados agora possui apenas homens e, portanto, não podemos incluir x3, a variável de gênero, no modelo. MAS...

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 é um problema com a notação "sinal de menos" na fórmula? Conselho por favor. Nota: Claro que posso fazer de uma maneira diferente; por exemplo, eu poderia excluir as variáveis ​​antes de colocá-las em lm (). Mas estou dando uma aula sobre esse assunto e não quero confundir os alunos, já tendo dito a eles que podem excluir variáveis ​​usando um sinal de menos na fórmula.

Zhaochen He
fonte
3
É interessante que ambos model.matrix(y ~ . - x3, data = dt[x3 == "men"])e model.matrix(y ~ x1 + x2, data = dt[x3 == "men"])trabalho ( lmchamadas model.matrixinternamente). A única diferença entre as duas matrizes de modelo é um "contrasts"atributo (que ainda contém x3) e é captado posteriormente na lmrotina, provavelmente causando o erro que você está vendo. Então, sinto que a questão está relacionada à maneira como model.matrixcria e armazena a matriz de design ao remover termos.
Maurits Evers
Eu estava tentando "expandir" o .para obter uma fórmula simplificada com, terms(y ~ . -x3, data=dt, simplify=TRUE)mas estranhamente ainda mantém x3o atributo de variáveis ​​que disparalm
MrFlick
11
@ MrFlick - parece que a opção não implementada em R neg.out=pode estar relacionada. Nos arquivos de ajuda do S terms, onde neg.out=é implementado: sinalizador que controla o tratamento dos termos inseridos com o sinal "-". Se TRUE, os termos serão verificados quanto ao cancelamento e, caso contrário, serão ignorados. Se FALSE, termos negativos serão mantidos (com ordem negativa).
thelatemail
11
@MauritsEvers: lmchama model.matrixuma versão modificada dos dados. Logo no início, lmcompõe e avalia a seguinte expressão: mf <- stats::model.frame( y ~ . -x3, dt[x3=="men"], drop.unused.levels=TRUE ). Isso faz x3com que se torne um fator de nível único. model.matrix()é então chamado mf, não os dados originais, resultando no erro que estamos observando.
Artem Sokolov

Respostas:

2

O erro que você está recebendo é porque x3 está no modelo com apenas um valor = "men"(veja o comentário abaixo em @Artem Sokolov)

Uma maneira de resolvê-lo é fazer um subconjunto com antecedência:

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)

Ou você pode fazer as duas coisas na mesma etapa:

lm( y ~ ., dt[x3 == 'men',-"x3"])
Dylan_Gomes
fonte
No geral, esta é uma boa solução. Uma coisa a corrigir é que -x3em uma fórmula não faz lmpensar que você está tentando subtrair a coluna. O "não use x3 no modelo" intenção é comunicada corretamente, mas o problema é que lmas chamadas model.frame( ..., drop.unused.levels=TRUE )causando x3a tornar-se um fator de nível único, levando a problemas a jusante model.matrix().
Artem Sokolov
Obrigado pelo esclarecimento Artem Sokolov, tirei essa explicação incorreta da minha resposta.
Dylan_Gomes