Este conjunto de dados é da Duke University Cardiovascular Disease Databank e consiste em 3504 pacientes e seis variáveis. Os pacientes foram encaminhados para a Duke University Medical Center com dor no peito. Algumas análises interessantes incluem prever a probabilidade de doença coronária (>= 75% de estreitamento do diámetro em pelo menos uma artéria coronária importante) e prever a probabilidade de doençca coronária grave, uma vez que é uma doença significativa.
A primeira análise usaria sigdz como variável de resposta e o segundo usaria tvdlm no subconjunto de pacientes com sigdz = 1. Doença coronária grave é definida como três vasos doentes ou doença principal na esquerda e é denotada por tvdlm = 1.
Leitura dos dados.
Hmisc::getHdata(acath)
attach(acath)
head(acath)
## sex age cad.dur choleste sigdz tvdlm
## 1 0 73 132 268 1 1
## 2 0 68 85 120 1 1
## 3 0 54 45 NA 1 0
## 4 1 58 86 245 0 0
## 5 1 56 7 269 0 0
## 6 0 64 0 NA 1 0
Sexo é denotado como: sex = 0 para o sexo masculino e 1 para o sexo feminino.
Variáveis:
Sexo = factor(sex,labels=c('Masculino','Feminino'))
Idade = age
cad.dur = Duração dos sintomas de doença arterial coronariana.
Resposta=factor(sigdz,levels=c(0,1),labels=c('Não','Sim'))
Colesterol = choleste
Cad.dur = cad.dur
rm(acath)
dados0 = data.frame(Resposta,Sexo,Idade,Colesterol,Cad.dur)
dados1 = na.exclude(dados0)
attach(dados1)
rm(dados0)
Resposta: sigdz
Sexo = factor(sex, levels=c(0,1), labels=c('Masculino','Feminino'))
Idade = age
Resposta = factor(sigdz, labels=c('Sim','Não'))
Colesterol = choleste
Cad.dur = cad.dur
dados0 = data.frame(Resposta,Sexo,Idade,Colesterol,Cad.dur)
dados1 = na.exclude(dados0)
attach(dados1)
par(mfrow=c(1,1), mar=c(3,3,1,1), cex=1.0)
mosaicplot(table(dados1$Resposta,dados1$Sexo), xlab='Doença coronária', main='')
ggpubr::ggstripchart(dados1, y = "Colesterol", x = "Sexo",
color = "Resposta", palette = c("#00AFBB", "#FC4E07"))
ggpubr::ggboxplot(dados1, y = "Colesterol", x = "Sexo",
color = "Resposta", palette = c("#00AFBB", "#FC4E07"))
ggpubr::ggstripchart(dados1, x = "Idade", y = "Colesterol", font.tickslab = c(8, "bold", "black"),
color = "Resposta", palette = c("#00AFBB", "#FC4E07"))
## Don't know how to automatically pick scale for object of type labelled/integer. Defaulting to continuous.
ggpubr::ggstripchart(dados1, x = "Resposta", y = "Cad.dur", color = "Sexo", palette = c("#00AFBB", "#FC4E07"))
## Don't know how to automatically pick scale for object of type labelled/integer. Defaulting to continuous.
plot(density(dados1$Colesterol), pch=19, ylab='Doença coronária', xlab='Colesterol', main="")
grid()
rug(dados1$Colesterol)
plot(dados1$Idade, dados1$Resposta, pch=19, ylab='Doença coronária', xlab='Idade')
plot(dados1$Cad.dur,dados1$Resposta,pch=19, ylab='Doença coronária', xlab='Duração dos sintomas')
plot(density(dados1$Idade[dados1$Resposta=="Não"]), xlab="Idade", ylab="Densidade estimada", main="Idade quando a resposta é negativa")
grid()
rug(dados1$Idade[dados1$Resposta=="Não"])
plot(density(dados1$Colesterol[dados1$Resposta=="Sim"]), xlab="Colesterol", ylab="Densidade estimada", main = "Colesterol quando a resposta é afirmativa")
grid()
rug(dados1$Colesterol[dados1$Resposta=="Sim"])
plot(density(dados1$Colesterol[dados1$Resposta=="Não"]), xlab="Colesterol", ylab="Densidade estimada", main = "Colesterol quando a resposta é negativa")
grid()
rug(dados1$Colesterol[dados1$Resposta=="Não"])
Percebemos que a doença coronária se manifesta mais no sexo masculino e está clara a influença da idade mas não do colesterol e nem da duração dos sintomas.
modelo00 = glm(Resposta ~ Idade + Sexo + Cad.dur + Colesterol, family=binomial(link='logit'), data = dados1)
modelo01 = update(modelo00, family=binomial(link='probit'))
modelo02 = update(modelo00, family=binomial(link='cloglog'))
modelo03 = update(modelo00, family=binomial(link='cauchit'))
Escolhendo a função de ligação.
AIC(modelo00,modelo01,modelo02,modelo03)
## df AIC
## modelo00 5 2354.626
## modelo01 5 2355.864
## modelo02 5 2353.651
## modelo03 5 2360.281
Selecionamos a função de ligação cloglog (menor valor de AIC).
modelo04 = step(modelo02)
## Start: AIC=2353.65
## Resposta ~ Idade + Sexo + Cad.dur + Colesterol
##
## Df Deviance AIC
## - Cad.dur 1 2345.4 2353.4
## <none> 2343.7 2353.7
## - Colesterol 1 2425.2 2433.2
## - Idade 1 2504.3 2512.3
## - Sexo 1 2750.3 2758.3
##
## Step: AIC=2353.43
## Resposta ~ Idade + Sexo + Colesterol
##
## Df Deviance AIC
## <none> 2345.4 2353.4
## - Colesterol 1 2425.5 2431.5
## - Idade 1 2509.8 2515.8
## - Sexo 1 2751.5 2757.5
De maneira automática descartamos somente a variável explicativa Cad.dur.
summary(modelo04)
##
## Call:
## glm(formula = Resposta ~ Idade + Sexo + Colesterol, family = binomial(link = "cloglog"),
## data = dados1)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.8908 -0.8981 0.5030 0.7978 2.0801
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.804673 0.228822 -12.257 <2e-16 ***
## Idade 0.040300 0.003337 12.078 <2e-16 ***
## SexoFeminino -1.323691 0.073485 -18.013 <2e-16 ***
## Colesterol 0.005414 0.000601 9.007 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 2895.3 on 2257 degrees of freedom
## Residual deviance: 2345.4 on 2254 degrees of freedom
## AIC: 2353.4
##
## Number of Fisher Scoring iterations: 5
par(mfrow=c(1,1),mar=c(5,4,1,1),cex=1.0)
Transformada = I(log(dados1$Colesterol*dados1$Idade))
lattice::xyplot(Transformada ~ Resposta | Sexo, data = dados1)
plot(dados1$Resposta ~ Transformada)
modelo05 = glm(Resposta ~ Idade + Sexo + Colesterol + Transformada, family=binomial(link='cloglog'), data=dados1)
Para calcular o R\(^2\) de Nagelkerke devemos utilizar a função lrm{rms}, The rms Package for R : Regression Modeling Strategies.
library(rms)
R2 = lrm(formula(modelo05), x=T, y=T, data=dados1)$stats[10]
R2
## R2
## 0.300897
O qual e um valor baixissimo!
par(mfrow=c(1,1),mar=c(5,4,1,1),cex=1.0)
plot(modelo05$y~fitted(modelo05), pch=19,cex=0.8, xlab='Valores preditos',
ylab='Valores observados')
grid()
ResourceSelection::hoslem.test(modelo05$y,fitted(modelo05))
##
## Hosmer and Lemeshow goodness of fit (GOF) test
##
## data: modelo05$y, fitted(modelo05)
## X-squared = 13.081, df = 8, p-value = 0.1091
O teste Hosmer-Lemeshow de bondade de ajuste aceita o ajuste do modelo (modelo05), porém no gráfico de valores estimados e observados percebemos que há muito erro nas estimativas da resposta.
mu.preditos=predict(modelo05,type='response')
PERGUNTA: para quais valores de estimativa da \(P(Y=1)\) assumir que o valor estimado da resposta é Y=1 e para quais Y=0?
Y.preditos1=ifelse(mu.preditos>0.5,1,0)
table(modelo05$y,Y.preditos1)
## Y.preditos1
## 0 1
## 0 385 383
## 1 186 1304
Y.preditos2=ifelse(mu.preditos>0.7,1,0)
table(modelo05$y,Y.preditos2)
## Y.preditos2
## 0 1
## 0 592 176
## 1 496 994
Y.preditos3=ifelse(mu.preditos>0.4,1,0)
table(modelo05$y,Y.preditos3)
## Y.preditos3
## 0 1
## 0 303 465
## 1 114 1376
Y.preditos4=ifelse(mu.preditos>0.9,1,0)
table(modelo05$y,Y.preditos4)
## Y.preditos4
## 0 1
## 0 745 23
## 1 1207 283