library("GLMsData")
library("splines")
library("MASS")
library("statmod")

data(downs)
head(downs)
##    Age Births DS
## 1 17.0  13555 16
## 2 18.5  13675 15
## 3 19.5  18752 16
## 4 20.5  22005 22
## 5 21.5  23896 16
## 6 22.5  24667 12
n <- dim(downs)[1]

Statistiques descriptives

summary(downs)
##       Age            Births            DS      
##  Min.   :17.00   Min.   :  249   Min.   : 7.0  
##  1st Qu.:24.75   1st Qu.: 4179   1st Qu.:13.0  
##  Median :32.00   Median :11485   Median :16.0  
##  Mean   :31.99   Mean   :11829   Mean   :17.3  
##  3rd Qu.:39.25   3rd Qu.:19090   3rd Qu.:21.5  
##  Max.   :47.10   Max.   :24807   Max.   :33.0
downs$Taux <- downs$DS/downs$Births
downs$Taux.1000 <- 1000*downs$Taux
summary(downs$Taux.1000)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.4865  0.8549  1.3099  6.2579  6.4561 36.9128
plot(downs$Age, downs$Births, type = "h", lwd = 3,
     xlab = "Age de la mere", ylab = "Nombre de naissances")

plot(downs$Age, downs$DS, pch = 19,
     xlab = "Age de la mere", ylab = "Nombre de naissances avec syndrome de Down")

plot(downs$Age, downs$Taux.1000, pch = 19,
     xlab = "Age de la mere", ylab = "Taux pour 1000 naissances")

plot(downs$Age, log(downs$Taux), pch = 19,
     xlab = "Age de la mere", ylab = "log(DS/Births)")

Définition du modèle

modele.lineaire <- glm(DS ~ offset(log(Births)) + Age,
                       family = poisson, data = downs)
summary(modele.lineaire)
## 
## Call:
## glm(formula = DS ~ offset(log(Births)) + Age, family = poisson, 
##     data = downs)
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -10.553981   0.214179  -49.28   <2e-16 ***
## Age           0.137191   0.006463   21.23   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for poisson family taken to be 1)
## 
##     Null deviance: 622.56  on 29  degrees of freedom
## Residual deviance: 183.03  on 28  degrees of freedom
## AIC: 326.1
## 
## Number of Fisher Scoring iterations: 5
modele.quadratique <- glm(DS ~ offset(log(Births)) + Age + I(Age^2),
                          family = poisson, data = downs)
summary(modele.quadratique)
## 
## Call:
## glm(formula = DS ~ offset(log(Births)) + Age + I(Age^2), family = poisson, 
##     data = downs)
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -2.3425778  0.6587995  -3.556 0.000377 ***
## Age         -0.4071225  0.0432067  -9.423  < 2e-16 ***
## I(Age^2)     0.0084991  0.0006705  12.677  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for poisson family taken to be 1)
## 
##     Null deviance: 622.56  on 29  degrees of freedom
## Residual deviance:  46.05  on 27  degrees of freedom
## AIC: 191.12
## 
## Number of Fisher Scoring iterations: 4
modele.logit <- glm(cbind(DS, Births - DS) ~ Age,
                    family = binomial(link = "logit"), data = downs)
cbind(coef(modele.lineaire), coef(modele.logit))
##                    [,1]        [,2]
## (Intercept) -10.5539807 -10.5634589
## Age           0.1371908   0.1375859

Modélisation de l’âge avec des splines

modele.ns.2 <- glm(DS ~ offset(log(Births)) + ns(Age, df = 2), family = poisson, data = downs)
modele.ns.3 <- glm(DS ~ offset(log(Births)) + ns(Age, df = 3), family = poisson, data = downs)
modele.ns.4 <- glm(DS ~ offset(log(Births)) + ns(Age, df = 4), family = poisson, data = downs)
modele.ns.5 <- glm(DS ~ offset(log(Births)) + ns(Age, df = 5), family = poisson, data = downs)
modele.ns.6 <- glm(DS ~ offset(log(Births)) + ns(Age, df = 6), family = poisson, data = downs)

AIC.modeles <- c(extractAIC(modele.lineaire, k = 2)[2],
                 extractAIC(modele.quadratique, k = 2)[2],
                 extractAIC(modele.ns.2, k = 2)[2],
                 extractAIC(modele.ns.3, k = 2)[2],
                 extractAIC(modele.ns.4, k = 2)[2],
                 extractAIC(modele.ns.5, k = 2)[2],
                 extractAIC(modele.ns.6, k = 2)[2])

BIC.modeles <- c(extractAIC(modele.lineaire, k = log(n))[2],
                 extractAIC(modele.quadratique, k = log(n))[2],
                 extractAIC(modele.ns.2, k = log(n))[2],
                 extractAIC(modele.ns.3, k = log(n))[2],
                 extractAIC(modele.ns.4, k = log(n))[2],
                 extractAIC(modele.ns.5, k = log(n))[2],
                 extractAIC(modele.ns.6, k = log(n))[2])

data.frame(modele = c("lineaire", "quadratique", "ns df=2", "ns df=3",
                      "ns df=4", "ns df=5", "ns df=6"),
           AIC = round(AIC.modeles, 2), BIC = round(BIC.modeles, 2))
##        modele    AIC    BIC
## 1    lineaire 326.10 328.90
## 2 quadratique 191.12 195.32
## 3     ns df=2 187.60 191.80
## 4     ns df=3 188.73 194.33
## 5     ns df=4 188.96 195.97
## 6     ns df=5 185.38 193.78
## 7     ns df=6 185.78 195.59
modele.bs <- glm(DS ~ offset(log(Births)) + bs(Age, knots = c(25, 35)),
                 family = poisson, data = downs)
extractAIC(modele.bs, k = 2)[2]
## [1] 184.9074
extractAIC(modele.bs, k = log(n))[2]
## [1] 193.3145
modele <- modele.ns.5
summary(modele)
## 
## Call:
## glm(formula = DS ~ offset(log(Births)) + ns(Age, df = 5), family = poisson, 
##     data = downs)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)       -6.6986     0.1901 -35.228  < 2e-16 ***
## ns(Age, df = 5)1  -0.1620     0.2511  -0.645    0.519    
## ns(Age, df = 5)2  -0.1007     0.3118  -0.323    0.747    
## ns(Age, df = 5)3   2.6314     0.2234  11.780  < 2e-16 ***
## ns(Age, df = 5)4   2.4182     0.4845   4.991 6.01e-07 ***
## ns(Age, df = 5)5   3.9408     0.2483  15.871  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for poisson family taken to be 1)
## 
##     Null deviance: 622.564  on 29  degrees of freedom
## Residual deviance:  34.307  on 24  degrees of freedom
## AIC: 185.38
## 
## Number of Fisher Scoring iterations: 4
p <- length(coef(modele)) - 1
stat.test.D <- deviance(modele.lineaire) - deviance(modele)
df.test <- modele.lineaire$df.residual - modele$df.residual
stat.test.D
## [1] 148.7215
1 - pchisq(stat.test.D, df = df.test)
## [1] 0

Interprétation du modèle

axe.age <- seq(min(downs$Age), max(downs$Age), 0.1)
nouvelles.donnees <- predict(modele, newdata = data.frame(Age = axe.age, Births = 1000),
                             se.fit = TRUE)
eta.chapeau <- nouvelles.donnees$fit
se.eta.chapeau <- nouvelles.donnees$se.fit
taux.chapeau <- exp(eta.chapeau)
borne.inf <- exp(eta.chapeau - 1.96*se.eta.chapeau)
borne.sup <- exp(eta.chapeau + 1.96*se.eta.chapeau)

plot(downs$Age, downs$Taux.1000, pch = 19,
     xlab = "Age de la mere", ylab = "Taux pour 1000 naissances")
lines(axe.age, taux.chapeau, col = "red")
lines(axe.age, borne.inf, lty = 2, col = "blue")
lines(axe.age, borne.sup, lty = 2, col = "blue")

plot(downs$Age, log(downs$Taux.1000), pch = 19,
     xlab = "Age de la mere", ylab = "log(Taux pour 1000 naissances)")
lines(axe.age, eta.chapeau, col = "red")
lines(axe.age, eta.chapeau - 1.96*se.eta.chapeau, lty = 2, col = "blue")
lines(axe.age, eta.chapeau + 1.96*se.eta.chapeau, lty = 2, col = "blue")

ages <- c(20, 25, 30, 35, 40, 45)
prediction.ages <- predict(modele, newdata = data.frame(Age = ages, Births = 1000),
                           se.fit = TRUE)
round(data.frame(Age = ages,
                 Taux.1000 = exp(prediction.ages$fit),
                 B.Inf = exp(prediction.ages$fit - 1.96*prediction.ages$se.fit),
                 B.Sup = exp(prediction.ages$fit + 1.96*prediction.ages$se.fit)), 3)
##   Age Taux.1000  B.Inf  B.Sup
## 1  20     0.851  0.707  1.025
## 2  25     0.723  0.603  0.866
## 3  30     1.001  0.806  1.241
## 4  35     1.685  1.342  2.115
## 5  40     8.000  6.764  9.462
## 6  45    27.552 21.380 35.506
taux.ages <- exp(prediction.ages$fit)
taux.ages/taux.ages[1]
##         1         2         3         4         5         6 
##  1.000000  0.848949  1.175182  1.979064  9.396580 32.360783

Validation du modèle

Adéquation globale

Deviance <- deviance(modele)
Pearson <- sum(resid(modele, type = "pearson")^2)
df <- modele$df.residual

(pvaleur.Deviance <- 1 - pchisq(Deviance, df = df))
## [1] 0.07935752
(pvaleur.Pearson <- 1 - pchisq(Pearson, df = df))
## [1] 0.05725585

Extra-variabilité

(phi.P.tilde <- Pearson/(n - (p+1)))
## [1] 1.492098
modele.quasi <- glm(DS ~ offset(log(Births)) + ns(Age, df = 5),
                    family = quasipoisson, data = downs)
summary(modele.quasi)
## 
## Call:
## glm(formula = DS ~ offset(log(Births)) + ns(Age, df = 5), family = quasipoisson, 
##     data = downs)
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -6.6986     0.2323 -28.839  < 2e-16 ***
## ns(Age, df = 5)1  -0.1620     0.3067  -0.528 0.602290    
## ns(Age, df = 5)2  -0.1007     0.3808  -0.264 0.793805    
## ns(Age, df = 5)3   2.6314     0.2729   9.643 9.94e-10 ***
## ns(Age, df = 5)4   2.4182     0.5919   4.086 0.000424 ***
## ns(Age, df = 5)5   3.9408     0.3033  12.993 2.37e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for quasipoisson family taken to be 1.492099)
## 
##     Null deviance: 622.564  on 29  degrees of freedom
## Residual deviance:  34.307  on 24  degrees of freedom
## AIC: NA
## 
## Number of Fisher Scoring iterations: 4
modele.NB <- glm.nb(DS ~ offset(log(Births)) + ns(Age, df = 5), link = "log", data = downs)
summary(modele.NB)
## 
## Call:
## glm.nb(formula = DS ~ offset(log(Births)) + ns(Age, df = 5), 
##     data = downs, link = "log", init.theta = 107.9419103)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -6.69908    0.20392 -32.852  < 2e-16 ***
## ns(Age, df = 5)1 -0.16602    0.26925  -0.617    0.538    
## ns(Age, df = 5)2 -0.09181    0.33409  -0.275    0.783    
## ns(Age, df = 5)3  2.62774    0.24278  10.824  < 2e-16 ***
## ns(Age, df = 5)4  2.42088    0.51908   4.664 3.11e-06 ***
## ns(Age, df = 5)5  3.94090    0.26265  15.004  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for Negative Binomial(107.9419) family taken to be 1)
## 
##     Null deviance: 568.415  on 29  degrees of freedom
## Residual deviance:  29.523  on 24  degrees of freedom
## AIC: 187.02
## 
## Number of Fisher Scoring iterations: 1
## 
## 
##               Theta:  108 
##           Std. Err.:  200 
## 
##  2 x log-likelihood:  -173.021
Q.obs <- deviance(modele) - deviance(modele.NB)
Q.obs
## [1] 4.783914
(pvalue <- (1 - pchisq(Q.obs, df = 1))/2)
## [1] 0.01436338

Résidus

residus.deviance <- resid(modele)
residus.Pearson <- resid(modele, type = "pearson")
residus.quantile <- qresid(modele)
residus.standardises <- rstandard(modele)
residus.studentises <- rstudent(modele)

plot(residus.deviance, xlab = "Numero d'observation", ylab = "Residus deviance")
abline(h = 0, col = "red")
abline(h = 3, lty = 2, col = "green")
abline(h = -3, lty = 2, col = "green")

plot(residus.Pearson, xlab = "Numero d'observation", ylab = "Residus Pearson")
abline(h = 0, col = "red")
abline(h = 3, lty = 2, col = "green")
abline(h = -3, lty = 2, col = "green")

scatter.smooth(residus.standardises ~ downs$Age,
               xlab = "Age de la mere", ylab = "Residus standardises")
abline(h = 0, col = "red")

plot(fitted(modele), residus.standardises,
     xlab = "Valeurs predites", ylab = "Residus standardises")
abline(h = 0, col = "red")

qqnorm(residus.quantile, xlab = "Quantiles theoriques",
       ylab = "Quantiles empiriques", main = "")
qqline(residus.quantile)

plot(fitted(modele), downs$DS, xlab = "Valeurs predites de DS",
     ylab = "Valeurs observees de DS")
abline(0, 1, col = "red")

Observations aberrantes et influentes

which(abs(as.vector(residus.standardises)) > 3)
## integer(0)
which(abs(as.vector(residus.studentises)) > 3)
## integer(0)
h <- hatvalues(modele)
(indices.h <- which(as.vector(h) > 3*(p+1)/n))
## [1] 1
d1 <- cooks.distance(modele)
max(d1)
## [1] 0.3979281
qf(0.5, p+1, n-(p+1))
## [1] 0.9168687
(indices.d1 <- which(as.vector(d1) > qf(0.5, p+1, n-(p+1))))
## integer(0)
d2 <- dffits(modele)
max(abs(d2))
## [1] 1.384648
3*sqrt(p/(n-p))
## [1] 1.341641
(indices.d2 <- which(as.vector(abs(d2)) > 3*sqrt(p/(n-p))))
## [1] 30
d3 <- dfbetas(modele)
max(abs(d3))
## [1] 1.262701
3/sqrt(n)
## [1] 0.5477226
d3.matrice <- abs(d3) > 3/sqrt(n)
(indices.d3 <- which(as.vector(rowSums(d3.matrice)) > 0))
## [1] 11 13 19 28 30
d4 <- covratio(modele)
max(abs(1-d4))
## [1] 2.21738
3*(p+1)/n
## [1] 0.6
(indices.d4 <- which(as.vector(abs(1-d4)) > 3*(p+1)/n))
## [1]  1  2 30
intersect(indices.d2, indices.d3)
## [1] 30
plot(d1, type = "h", xlab = "Numero d'observation", ylab = "Distance de Cook")
abline(h = qf(0.5, p+1, n-(p+1)), lty = 2, col = "red")

plot(h, xlab = "Numero d'observation", ylab = "Leviers")
abline(h = 3*(p+1)/n, lty = 2, col = "red")

indices <- intersect(indices.d2, indices.d3)
modele.sans <- glm(DS ~ offset(log(Births)) + ns(Age, df = 5),
                   family = poisson, data = downs[-indices, ])

data.frame(coef.avec = coef(modele), coef.sans = coef(modele.sans))
##                   coef.avec  coef.sans
## (Intercept)      -6.6985589 -6.6948587
## ns(Age, df = 5)1 -0.1619720 -0.2180973
## ns(Age, df = 5)2 -0.1006517 -0.1061848
## ns(Age, df = 5)3  2.6313948  2.0608604
## ns(Age, df = 5)4  2.4181918  2.2075907
## ns(Age, df = 5)5  3.9408316  3.8623114
data.frame(s.e.avec = sqrt(diag(vcov(modele))),
           s.e.sans = sqrt(diag(vcov(modele.sans))))
##                   s.e.avec  s.e.sans
## (Intercept)      0.1901494 0.1923201
## ns(Age, df = 5)1 0.2510948 0.2555288
## ns(Age, df = 5)2 0.3117636 0.3214309
## ns(Age, df = 5)3 0.2233863 0.2262517
## ns(Age, df = 5)4 0.4845314 0.4819683
## ns(Age, df = 5)5 0.2483096 0.2068306