# Nomes dos pacotes
packages <- c("foreign", "nnet", "ggplot2", "reshape2", "kableExtra")
# Instala os pacotes que ainda não foram instalados
installed_packages <- packages %in% rownames(installed.packages())
if (any(installed_packages == FALSE)) {
install.packages(packages[!installed_packages])
}
# Carrega os pacotes
invisible(lapply(packages, library, character.only = TRUE))
A regressão logística nominal é usada para modelar variáveis categóricas nominais.
Exemplo Os alunos ingressantes no ensino médio fazem escolhas de programa entre programa geral, programa vocacional e programa acadêmico. A escolha pode ser modelada usando sua pontuação de escrita e o status socioeconômico de cada aluno.
O banco de dados utilizado no modelo é o ‘hsbdemo’.
ml <- read.dta("https://stats.idre.ucla.edu/stat/data/hsbdemo.dta")
head(ml) %>%
kbl() %>%
kable_styling("hover", full_width = F)
| id | female | ses | schtyp | prog | read | write | math | science | socst | honors | awards | cid |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 45 | female | low | public | vocation | 34 | 35 | 41 | 29 | 26 | not enrolled | 0 | 1 |
| 108 | male | middle | public | general | 34 | 33 | 41 | 36 | 36 | not enrolled | 0 | 1 |
| 15 | male | high | public | vocation | 39 | 39 | 44 | 26 | 42 | not enrolled | 0 | 1 |
| 67 | male | low | public | vocation | 37 | 37 | 42 | 33 | 32 | not enrolled | 0 | 1 |
| 153 | male | middle | public | vocation | 39 | 31 | 40 | 39 | 51 | not enrolled | 0 | 1 |
| 51 | female | high | public | general | 42 | 36 | 42 | 31 | 39 | not enrolled | 0 | 1 |
O conjunto de dados contém variáveis referente a 200 alunos. A variável resposta é prog, que é tipo de programa. As variáveis preditoras são status socioeconômico (ses) que é uma variável categórica com três níveis e pontuação de escrita (write) que é uma variável contínua.
Abaixo são apresentadas algumas estatísticas descritivas das variáveis de interesse, como frequência para cada grupo, média e desvio padrão.
kbl(with(ml, table(ses, prog))) %>%
kable_styling("hover", full_width = F)
| general | academic | vocation | |
|---|---|---|---|
| low | 16 | 19 | 12 |
| middle | 20 | 44 | 31 |
| high | 9 | 42 | 7 |
kbl(with(ml, do.call(rbind, tapply(write, prog, function(x) c(Media = round(mean(x),2), DP = round(sd(x),2)))))) %>%
kable_styling("hover", full_width = F)
| Media | DP | |
|---|---|---|
| general | 51.33 | 9.40 |
| academic | 56.26 | 7.94 |
| vocation | 46.76 | 9.32 |
Utilizando a função multinom do pacote nnet, estimaremos um modelo de regressão logística nominal.
Primeiro, escolhemos a categoria de referência do desfecho, especificando com o uso da função relevel. Em seguida, calculamos o p-valor para os testes dos coeficientes da regressão, através do teste de Wald.
ml$prog2 <- relevel(ml$prog, ref = 'academic')
test <- multinom(prog2 ~ ses + write, data = ml) # nnet::multinom(prog2 ~ ses + write, data = ml)
## # weights: 15 (8 variable)
## initial value 219.722458
## iter 10 value 179.982880
## final value 179.981726
## converged
summary(test) # resumo dos resultados obtidos pelo modelo ajustado
## Call:
## multinom(formula = prog2 ~ ses + write, data = ml)
##
## Coefficients:
## (Intercept) sesmiddle seshigh write
## general 2.852198 -0.5332810 -1.1628226 -0.0579287
## vocation 5.218260 0.2913859 -0.9826649 -0.1136037
##
## Std. Errors:
## (Intercept) sesmiddle seshigh write
## general 1.166441 0.4437323 0.5142196 0.02141097
## vocation 1.163552 0.4763739 0.5955665 0.02221996
##
## Residual Deviance: 359.9635
## AIC: 375.9635
A saída de resumo do modelo possui um bloco de coeficientes e um bloco de erros padrão. Cada um desses blocos possui uma linha de valores correspondente a uma equação do modelo.
\(\beta_{13} = -0.0579287 \approx -0.06\)
**Interpretação: existe uma redução aproximada de 0,06 no logaritmo da chance da escolha do programa geral, em relação a acadêmica, dado o aumento em uma unidade no score de escrita.
\(\beta_{21} = 0.2914 \approx 0.30\)
**Interpretação: existe um aumento de aproximadamente 0,30 no logaritmo da chance da escolha do programa vocacional, em relação a acadêmico, dado a mudança do status social baixo para médio.
z <- summary(test)$coefficients/summary(test)$standard.errors # estatística do valor-z
kbl(round(z,1), caption = "Estatística do Teste de Wald") %>%
kable_styling("hover", full_width = F)
| (Intercept) | sesmiddle | seshigh | write | |
|---|---|---|---|---|
| general | 2.4 | -1.2 | -2.3 | -2.7 |
| vocation | 4.5 | 0.6 | -1.6 | -5.1 |
O valor-z é uma estatística de teste para testes que medem a razão entre o coeficiente e seu erro padrão. Ele é utilizado para calcular o valor-p, auxiliando na tomada de uma decisão sobre a significância estatística dos termos.
p <- (1 - pnorm(abs(z),0,1)) * 2 # teste de Wald bilateral
kbl(round(p,4)) %>%
kable_styling("hover", full_width = F)
| (Intercept) | sesmiddle | seshigh | write | |
|---|---|---|---|---|
| general | 0.0145 | 0.2294 | 0.0237 | 0.0068 |
| vocation | 0.0000 | 0.5408 | 0.0989 | 0.0000 |
O p-valor é uma medida de probabilidade que mede a evidência contra a hipótese nula. As estimativas mais próximas a zero (valor p menor que 0,05, supondo 5% de significância) fornecem evidências mais fortes contra a hipótese nula.
As razões de chances são as medidas de associação produzidas por modelos de regressão logística. Neste modelo elas são obtidas exponenciando os coeficientes de regressão.
kbl(round(exp(coef(test)),4)) %>%
kable_styling("hover", full_width = F)
| (Intercept) | sesmiddle | seshigh | write | |
|---|---|---|---|---|
| general | 17.3258 | 0.5867 | 0.3126 | 0.9437 |
| vocation | 184.6126 | 1.3383 | 0.3743 | 0.8926 |
\(0.9437 \approx 0.94\)
\(100\% - 94\% = 6\%\)
**Interpretação: o aumento em uma unidade na variável write acarreta uma redução aproximada de 6% na chance de se escolher o programa geral ao invés do acadêmico.
\(0.3126 \approx 0.31\)
\(100\% - 31\% = 69\%\)
**Interpretação: mudar o status da classe social baixa para alta reduz aproximadamente 69% a chance de se escolher o programa geral ao invés do acadêmico.
\(1.3383 \approx 1.34\)
\(1.34 - 1 = 0.34\)
**Interpretação: mudar o status da classe social baixa para média aumenta aproximadamente 34% a chance de se escolher o programa vocacional ao invés do acadêmico (esta razão de chances é não significativa).
kbl(round(exp(confint(test)),2)) %>%
kable_styling("hover", full_width = F)
| 2.5 %.general | 97.5 %.general | 2.5 %.vocation | 97.5 %.vocation | |
|---|---|---|---|---|
| (Intercept) | 1.76 | 170.44 | 18.87 | 1805.84 |
| sesmiddle | 0.25 | 1.40 | 0.53 | 3.40 |
| seshigh | 0.11 | 0.86 | 0.12 | 1.20 |
| write | 0.90 | 0.98 | 0.85 | 0.93 |
Estes intervalos de confiança (IC95%) permitem ao pesquisador conhecer a precisão das estimativas das razões de chances.
É possível estimar as probabilidades preditas para os sujeitos da amostra de acordo com seu status social e seu score de escrita, usando a função fitted.
kbl(round(head(pp <- fitted(test)),4)) %>%
kable_styling("hover", full_width = F)
| academic | general | vocation |
|---|---|---|
| 0.1483 | 0.3382 | 0.5135 |
| 0.1202 | 0.1806 | 0.6992 |
| 0.4187 | 0.2368 | 0.3445 |
| 0.1727 | 0.3508 | 0.4765 |
| 0.1001 | 0.1689 | 0.7309 |
| 0.3534 | 0.2378 | 0.4088 |
Foram criados pequenos conjuntos de dados, variando uma variável enquanto mantemos a outra constante. Primeiro mantendo fixa a média de write e examinando as probabilidades preditas para cada nível de ses.
dses <- data.frame(ses = c("low", "middle", "high"), write = mean(ml$write))
kbl(round(predict(test, newdata = dses, "probs"),4)) %>%
kable_styling("hover", full_width = F)
| academic | general | vocation |
|---|---|---|
| 0.4397 | 0.3582 | 0.2021 |
| 0.4777 | 0.2283 | 0.2939 |
| 0.7009 | 0.1785 | 0.1206 |
Outra maneira de entender o modelo usando as probabilidades preditas é olhar para as probabilidades médias preditas para os diferentes valores da variável preditora contínua write dentro de cada nível de ses.
dwrite <- data.frame(ses = rep(c("low", "middle", "high"), each = 41), write = rep(c(30:70),
3))
## armazena as probabilidades preditas para cada valor de ses e write
pp.write <- cbind(dwrite, predict(test, newdata = dwrite, type = "probs", se = TRUE))
## calcula as probabilidades médias dentro de cada nível de ses
by(pp.write[, 3:5], pp.write$ses, colMeans)
## pp.write$ses: high
## academic general vocation
## 0.6164315 0.1808037 0.2027648
## ------------------------------------------------------------
## pp.write$ses: low
## academic general vocation
## 0.3972977 0.3278174 0.2748849
## ------------------------------------------------------------
## pp.write$ses: middle
## academic general vocation
## 0.4256198 0.2010864 0.3732938
lpp <- melt(pp.write, id.vars = c("ses", "write"), value.name = "probability")
ggplot(lpp, aes(x = write, y = probability, colour = ses)) +
geom_line() +
facet_grid(variable ~ ., scales = "free") +
theme_minimal()
Com a análise gráfica acima podemos evidenciar que o aluno que possui uma classe social mais alta está relacionado ao programa acadêmico. Além disso, na escolha do programa vocacional ao acadêmico, o status social baixo muda para alto.