Aula de Regressão Logística Simples no R


 

Este primeiro exemplo tratará da regressão logística simples, portanto, utilizando somente uma variável independente, neste caso numérica.

Trata-se de uma amostra com 100 pessoas. A variável dependente é a ocorrência ou não (1 ou 0) de doença coronária cardíaca (CHD), associando-se com a idade (AGE) dos indivíduos, criando assim um modelo de regressão logística.

Limpar o R

rm(list=ls())

Instalar os pacotes caso ainda não tenha instalado tirar o # da frente de install.packages para funcionar

#Instalando pacotes
#install.packages(c("ggplot2","readr","mfx","caret","pRoc", "ResourceSelection","modEvA","foreign","stargazer", "DataExplorer", "yardstick"))
#Carregando pacotes exigidos:
library(readr)
library(dplyr)
library(ggplot2)
library(mfx)
library(caret)
library(pROC)
library(ResourceSelection)
library(modEvA)
library(foreign)
library(stargazer)
library(DataExplorer)
library(yardstick)
library(kableExtra)

Ler os dados disponíveis na internet

chd <- read_delim("https://github.com/Smolski/livroavancado/raw/master/cdh.csv", 
                  ";", escape_double = FALSE, col_types = cols(CHD = col_factor(levels = c())), 
                  trim_ws = TRUE)

Visualizar os dados

kable(head(chd, 10)) %>%
  kable_styling(full_width = F, bootstrap_options = c("striped", "hover", "condensed", "responsive"))
AGEAGRPCHD
2010
2310
2410
2510
2511
2610
2610
2810
2810
2910
summary(chd)
##       AGE             AGRP      CHD   
##  Min.   :20.00   Min.   :1.00   0:57  
##  1st Qu.:34.75   1st Qu.:2.75   1:43  
##  Median :44.00   Median :4.00         
##  Mean   :44.38   Mean   :4.48         
##  3rd Qu.:55.00   3rd Qu.:7.00         
##  Max.   :69.00   Max.   :8.00
str(chd)
## spc_tbl_ [100 × 3] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ AGE : num [1:100] 20 23 24 25 25 26 26 28 28 29 ...
##  $ AGRP: num [1:100] 1 1 1 1 1 1 1 1 1 1 ...
##  $ CHD : Factor w/ 2 levels "0","1": 1 1 1 1 2 1 1 1 1 1 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   AGE = col_double(),
##   ..   AGRP = col_double(),
##   ..   CHD = col_factor(levels = NULL, ordered = FALSE, include_na = FALSE)
##   .. )
##  - attr(*, "problems")=<externalptr>
glimpse(chd)
## Rows: 100
## Columns: 3
## $ AGE  <dbl> 20, 23, 24, 25, 25, 26, 26, 28, 28, 29, 30, 30, 30, 30, 30, 30, 3…
## $ AGRP <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,…
## $ CHD  <fct> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,…

Mostrar o gráfico de dispersão das observações Eixo x é idade e eixo y é possui ou não a doença CHD (1 possui e 0 não possui)

ggplot(chd, aes(x=AGE, y=CHD)) + 
  geom_point() + 
  stat_smooth(method="glm", method.args=list(family="binomial"), se=FALSE)

m1=glm(CHD~AGE, family = binomial(link="logit"), data = chd)
summary(m1)
## 
## Call:
## glm(formula = CHD ~ AGE, family = binomial(link = "logit"), data = chd)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.9718  -0.8456  -0.4576   0.8253   2.2859  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -5.30945    1.13365  -4.683 2.82e-06 ***
## AGE          0.11092    0.02406   4.610 4.02e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 136.66  on 99  degrees of freedom
## Residual deviance: 107.35  on 98  degrees of freedom
## AIC: 111.35
## 
## Number of Fisher Scoring iterations: 4

Se observa o intercepto com o valor de -5,309, sendo que para a análise aqui proposta da relação entre CHD e AGE não obtém-se um significado prático para este resultado.No entanto, a variável de interesse é idade, que no modelo de regressão obteve o coeficiente de 0,1109. Pelo fato de ser positivo informa que quando a idade (AGE) se eleva, elevam-se as chances de ocorrência de CHD.De igual forma, nota-se que há significância estatística a p = 0,001 na utilização da variável AGE para o modelo, mostrando que possui importância ao modelo de regressão proposto.

Por fim, o modelo é utilizado para construção da predição de todos os valores das idades de todos os indivíduos desta amostra. Para isto, será criada um novo objeto contendo somente a variável dependente do modelo (AGE) e em seguida, é criada nova coluna constando os valores preditos. Assim, pode ser plotado um gráfico completo com todas as probabilidades desta base de dados:

# Filtrando a idade dos indivíduos
IDADE<-chd[,1]
# Criando campo de predição para cada idade dos indivíduos 
chd$PRED=predict(m1, newdata=IDADE, type="response")

Plotando a probabilidade predita pelo modelo

ggplot(chd, aes(x=AGE, y=PRED)) + 
  geom_point()

Estimando a Razão de Chances

logitor(CHD~AGE,data = chd)
## Call:
## logitor(formula = CHD ~ AGE, data = chd)
## 
## Odds Ratio:
##     OddsRatio Std. Err.      z     P>|z|    
## AGE  1.117307  0.026882 4.6102 4.022e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

O modelo de regressão logística, porém, traz os resultados dos estimadores na forma logarítma, ou seja, o log das chances da variável idade no modelo é 0,1109. No entanto, para uma interpretação mais enriquecida da relação da idade com o CHD é necessária a transformação deste coeficiente, ou seja, que seja efetuada a exponenciação da(s) variavel(eis) da regressão. Assim, obtém-se a razão das chances (OR - Odds Ratio em inglês) para as variáveis independentes.

Uma maneira prática de se obter a razão de chances no RStudio é utilizando o pacote mfx. Novamente o intercepto não nos interessa nesta análise mas sim a variável AGE. Como demonstrado abaixo, o resultado da razão de chances da variável AGE foi de 1,1173, o que pode assim ser interpretado: para cada variação unitária na idade (AGE), as chances de ocorrência de CHD aumentam 1,1173 vezes. Dito de outra forma, para cada variação unitária em AGE, aumentam-se 11,73% ((1,1173-1)*100) as chances da ocorrência de CHD.

Determinando o Intervalo de Confiança

exp(cbind(OR=coef(m1), confint(m1)))
##                      OR        2.5 %    97.5 %
## (Intercept) 0.004944629 0.0004412621 0.0389236
## AGE         1.117306795 1.0692223156 1.1758681

A determinação do intervalo de confiança do modelo proposto é relevante para que seja analizada a estimativa do intervalo de predição do coeficiente da variável independente, a um nível de confiança de 95%. Desta forma, em 95% dos casos, o parâmetro dos coeficientes estará dentro deste intervalo.

De forma prática é possível determinar os intervalos de confiança com o comando confint() commo observado abaixo, sendo que o coeficiente AGE toma o valor de 1,1173, podendo variar de 1,0692 a 1,1758.

Predição de Probabilidades

media = data.frame(AGE=mean(chd$AGE))
media
##     AGE
## 1 44.38

A partir dos coeficientes do modelo de regressão logística é possível, portanto, efetuar a predição da variável categórica CHD, ou seja, saber a chance de ocorrer CHD com relação à uma determinada idade (AGE). No exemplo abaixo, primeiramente utilizamos a idade média das observações (44,38 anos), criando assim um novo data.frame chamado media.

media$pred.prob = predict(m1, newdata=media, type="response")
media
##     AGE pred.prob
## 1 44.38 0.4044944

Para utilizar o valor da idade média na função de regressão obtida (m1), utiliza-se a função predict(), de acordo com valor da média encontrada (data.frame media).

O resultado mostra que para a idade média da amostra, 44,38 anos, há uma probabilidade de 40,44% na ocorrência da doença CHD. Esta ferramenta permite também a comparação pelo pesquisador das diferentes probabilidades entre as diversas idades (variável AGE).

Matriz de Confusão

chd$pdata <- as.factor(
  ifelse(
    predict(m1, 
            newdata = chd, 
            type = "response")
    >0.5,"1","0"))

caret::confusionMatrix(chd$pdata, chd$CHD, positive="1")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 45 14
##          1 12 29
##                                           
##                Accuracy : 0.74            
##                  95% CI : (0.6427, 0.8226)
##     No Information Rate : 0.57            
##     P-Value [Acc > NIR] : 0.0003187       
##                                           
##                   Kappa : 0.4666          
##                                           
##  Mcnemar's Test P-Value : 0.8445193       
##                                           
##             Sensitivity : 0.6744          
##             Specificity : 0.7895          
##          Pos Pred Value : 0.7073          
##          Neg Pred Value : 0.7627          
##              Prevalence : 0.4300          
##          Detection Rate : 0.2900          
##    Detection Prevalence : 0.4100          
##       Balanced Accuracy : 0.7319          
##                                           
##        'Positive' Class : 1               
## 

A matriz de confusão retoma uma excelente acurácia total do modelo em 74%, sendo que o modelo consegue acertos de 70,7% na predição de valores positivos ou dos “eventos” (29/41) e 76,3% na predição de valores negativos ou os “não eventos” (45/59).

Curva ROC

roc1=plot.roc(chd$CHD,fitted(m1))

plot(roc1,
     print.auc=TRUE, 
     auc.polygon=TRUE, 
     grud=c(0.1,0.2),
     grid.col=c("green","red"), 
     max.auc.polygon=TRUE, 
     auc.polygon.col="lightgreen", 
     print.thres=TRUE)

O teste Hosmer e Lemeshow

hl=hoslem.test(chd$CHD,fitted(m1),g=10)
hl
## 
##  Hosmer and Lemeshow goodness of fit (GOF) test
## 
## data:  chd$CHD, fitted(m1)
## X-squared = 100, df = 8, p-value < 2.2e-16

O teste de Hosmer e Lemeshow é utilizado para demonstrar a qualidade do ajuste do modelo, ou seja, se o modelo pode explicar os dados observados. Para este teste, os dados são divididos de acordo com as probabilidades previstas em 10 grupos iguais, sendo que os números previstos e os reais são comparados com a estatística do qui-quadrado. Hair et al. (2009) sugerem um tamanho de amostra de pelo menos 50 casos para a realização deste teste.

A hipótese nula H0 do qui-quadrado (p=0,05) deste teste é a de que as proporções observadas e esperadas são as mesmas ao longo da amostra. O modelo apresenta dificuldade de ajuste em função de que rejeita a hipótese nula a p=0,05.

Um grande valor de qui-quadrado (com pequeno valor de p < 0,05) indica um ajuste ruim e pequenos valores de qui-quadrado (com maior valor de p próximo a 1) indicam um bom ajuste do modelo de regressão logística.

Pseudo R2

RsqGLM(m1)

## $CoxSnell
## [1] 0.2540516
## 
## $Nagelkerke
## [1] 0.3409928
## 
## $McFadden
## [1] 0.2144684
## 
## $Tjur
## [1] 0.2705749
## 
## $sqPearson
## [1] 0.2725518

Semelhante ao coeficiente de determinação R2 da regressão múltipla, a medida de pseudo R2 representam o ajuste geral do modelo proposto. Sua interpretação, portanto, é semelhante à regressão múltipla.

O modelo CoxSnell, por exemplo,explica 25% da variação na variável dependente. No entanto, é chamado de pseudo porque não é exatamente o R2 da regressão linear.

Comentários

Postagens mais visitadas