Como forçar R a usar um nível de fator especificado como referência em uma regressão?

112

Como posso dizer a R para usar um determinado nível como referência se eu usar variáveis ​​explicativas binárias em uma regressão?

Ele está apenas usando algum nível por padrão.

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

com b {0, 1, 2, 3, 4}. Digamos que eu queira usar 3 em vez do zero que é usado por R.

Matt Bannert
fonte
9
Você deve realizar a etapa de processamento de dados fora da fórmula / ajuste do modelo. Ao criar o fator de, bvocê pode especificar a ordem dos níveis usando factor(b, levels = c(3,1,2,4,5)). No lm()entanto, faça isso em uma etapa de processamento de dados fora da chamada. Minha resposta abaixo usa a relevel()função para que você possa criar um fator e, em seguida, mudar o nível de referência para se adequar conforme necessário.
Gavin Simpson,
1
Eu reformulei sua pergunta. Na verdade, você está mudando o nível de referência, não deixando nenhum de fora.
Joris Meys
obrigado por reformular minha pergunta. Na verdade, relevel () era o que eu procurava. Obrigado pela resposta detalhada e pelo exemplo. Não tenho certeza se a etiqueta de regressão linear é um pouco enganosa porque isso se aplica a todos os tipos de regressão usando explicações fictícias ...
Matt Bannert,

Respostas:

152

Veja a relevel()função. Aqui está um exemplo:

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)

Agora altere o fator bem DFpelo uso da relevel()função:

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

Os modelos estimaram diferentes níveis de referência.

> 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
fonte
9
Para preseve a variável original, basta não usar o within, mas df$bR = relevel(df$b, ref=3).
BurninLeo
1
Você pode usar relevel () dentro de sua fórmula, não afetaria o conjunto de dados original ...
Mehdi Zare
36

Outros mencionaram o relevelcomando que é a melhor solução se você deseja alterar o nível de base para todas as análises em seus dados (ou está disposto a conviver com a alteração dos dados).

Se você não quiser alterar os dados (esta é uma alteração única, mas no futuro você deseja o comportamento padrão novamente), então você pode usar uma combinação da função C(note maiúsculas) para definir contrastes e a contr.treatmentsfunção com o argumento base para escolher qual nível você deseja ser a linha de base.

Por exemplo:

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

O relevel()comando é um método abreviado para sua pergunta. O que ele faz é reordenar o fator de modo que seja o que for o nível de referência, primeiro. Portanto, reorganizar seus níveis de fator também terá o mesmo efeito, mas oferece mais controle. Talvez você queira ter níveis 3,4,0,1,2. Nesse caso...

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

Prefiro esse método porque é mais fácil para mim ver em meu código não apenas qual era a referência, mas também a posição dos outros valores (em vez de ter que olhar os resultados para isso).

NOTA: NÃO faça disso um fator ordenado. Um fator com uma ordem especificada e um fator ordenado não são a mesma coisa. lm()pode começar a pensar que você deseja contrastes polinomiais se fizer isso.

John
fonte
2
Contrastes polinomiais, não uma regressão polinomial.
hadley,
Existe uma maneira de definir o nível de referência ao mesmo tempo que você define o fator, em vez de em uma chamada subsequente para relevel?
David Bruce Borenstein,
31

Eu sei que esta é uma pergunta antiga, mas tive um problema semelhante e descobri que:

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

faz exatamente o que você pediu.

Yan Alperovych
fonte
3
Isto foi uma grande ajuda! A única solução que incluía uma maneira de fazer isso dentro do comando lm () que era exatamente o que eu precisava. Obrigado!
cparmstrong
3
Esta é uma forma muito flexível de trabalhar com fatores. Gosto do fato de poder combiná-lo com, as.factor()se necessário, por exemplo, usando...+relevel(as.factor(mycol), ref = "myref")+...
Peter
12

Você também pode marcar manualmente a coluna com um contrastsatributo, que parece ser respeitado pelas funções de regressão:

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

Para quem procura uma versão dplyr / tidyverse. Com base na solução 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
fonte
Estou confuso por que você colocou "Se a variável é um fator" onde você colocou ... isso é necessário se você usar relevel()ouforcats::fct_relevel()
Gregor Thomas
Você está correto, obrigado! Eu adicionei "você também pode usar", porque, afaik, fct_relevel só funciona com fatores.
Gorka
2
relevelsó funciona com fatores. fct_relevelsó funciona com fatores. Não há nenhuma diferença entre as funções, exceto o nome, AFAIK. Dizer "Se a variável é um fator, você também pode usar fct_relevel" implica que, se a variável não for um fator, você pode usar relevel, mas isso não é verdade.
Gregor Thomas,