Modèles linéaires
La régression linéaire sert à modéliser la relation linéaire entre une variable dépendante et une ou plusieurs variables indépendantes. Rappelez-vous qu’un coefficient de régression représente la variation moyenne de la variable dépendante associée à une augmentation d’une unité de la variable indépendante.
Dans ce laboratoire, nous allons (1) charger un jeu de données du
package datasets, (2) représenter graphiquement la relation
entre deux et trois variables, (3) effectuer des régressions linéaires
simples et multiples avec lm() et (4) introduire les
modèles polynomiaux. Les exercices se trouvent à la toute fin du
document.
Fonctions pertinentes : lm(),
summary()
Petit rappel : en R, le symbole <-
sert à assigner (c’est-à-dire à stocker) une valeur dans un
objet. Par exemple, modele1 <- lm(...) signifie «
stocker les résultats de la régression dans l’objet nommé modele1 ».
# Charger les packages utilisés dans ce laboratoire
# (au besoin, installez-les d'abord avec install.packages())
library(datasets)
library(ggplot2)
library(broom)
library(plotly)
1. Charger les données
Nous utilisons le jeu de données swiss du package
datasets. Il contient une mesure standardisée de la
fécondité ainsi que des indicateurs socioéconomiques pour 47
provinces francophones de la Suisse en 1888.
Le package datasets est installé par défaut avec R : une
fois chargé avec library(), on peut utiliser directement le
data frame swiss dans n’importe quelle fonction.
dim(swiss) # Vérifier les dimensions du jeu de données (lignes, colonnes)
## [1] 47 6
colnames(swiss) # Afficher le nom des colonnes
## [1] "Fertility" "Agriculture" "Examination" "Education"
## [5] "Catholic" "Infant.Mortality"
head(swiss, 10) # Afficher les 10 premières observations
## Fertility Agriculture Examination Education Catholic
## Courtelary 80.2 17.0 15 12 9.96
## Delemont 83.1 45.1 6 9 84.84
## Franches-Mnt 92.5 39.7 5 5 93.40
## Moutier 85.8 36.5 12 7 33.77
## Neuveville 76.9 43.5 17 15 5.16
## Porrentruy 76.1 35.3 9 7 90.57
## Broye 83.8 70.2 16 7 92.85
## Glane 92.4 67.8 14 8 97.16
## Gruyere 82.4 53.3 12 7 97.67
## Sarine 82.9 45.2 16 13 91.38
## Infant.Mortality
## Courtelary 22.2
## Delemont 22.2
## Franches-Mnt 20.2
## Moutier 20.3
## Neuveville 20.6
## Porrentruy 26.6
## Broye 23.6
## Glane 24.9
## Gruyere 21.0
## Sarine 24.4
Voici la description des variables de ce jeu de données :
| Nom de la variable | Description |
|---|---|
| Fertility | Indice standardisé de fécondité |
| Agriculture | % des hommes travaillant dans le secteur agricole |
| Examination | % des conscrits ayant obtenu la note maximale à l’examen de l’armée |
| Education | % des conscrits ayant une scolarité au-delà du primaire |
| Catholic | % de catholiques |
| Infant.Mortality | % des enfants nés vivants décédés avant l’âge d’un an |
Ici, l’unité d’observation n’est pas l’individu, mais la province : il s’agit de données agrégées. Le nom de chaque province se trouve dans le nom des lignes.
rownames(swiss) # Afficher le nom des lignes (les provinces)
## [1] "Courtelary" "Delemont" "Franches-Mnt" "Moutier" "Neuveville"
## [6] "Porrentruy" "Broye" "Glane" "Gruyere" "Sarine"
## [11] "Veveyse" "Aigle" "Aubonne" "Avenches" "Cossonay"
## [16] "Echallens" "Grandson" "Lausanne" "La Vallee" "Lavaux"
## [21] "Morges" "Moudon" "Nyone" "Orbe" "Oron"
## [26] "Payerne" "Paysd'enhaut" "Rolle" "Vevey" "Yverdon"
## [31] "Conthey" "Entremont" "Herens" "Martigwy" "Monthey"
## [36] "St Maurice" "Sierre" "Sion" "Boudry" "La Chauxdfnd"
## [41] "Le Locle" "Neuchatel" "Val de Ruz" "ValdeTravers" "V. De Geneve"
## [46] "Rive Droite" "Rive Gauche"
2. Relation bivariée
Commençons par un modèle de régression linéaire simple, qui examine la relation entre une variable indépendante (la mortalité infantile) et une variable dépendante (la fécondité). Notez que le sens de cette relation n’est pas évident : on pourrait aussi penser que plus de naissances entraînent plus de décès d’enfants. C’est ce qu’on appelle un problème d’endogénéité.
2.1 Représenter nos données graphiquement
La première étape consiste à vérifier visuellement s’il semble y avoir une relation linéaire entre la mortalité infantile et la fécondité, à l’aide d’un nuage de points.
ggplot(data=swiss, aes(Infant.Mortality, Fertility)) +
geom_point() +
xlab("Mortalité infantile (%)") + ylab("Indice de fécondité") +
theme_minimal(base_size = 20) +
xlim(0,30)
À première vue, les deux variables semblent-elles corrélées? Si oui, la relation semble-t-elle positive ou négative?
2.2 Estimer un modèle MCO avec lm()
Avec lm(), on précise la formule d’une régression
linéaire simple : variable dépendante ~ variable
indépendante. La fonction lm() estime une
ordonnée à l’origine et un coefficient de
régression. L’ordonnée à
l’origine (intercept) représente la valeur
prédite de la variable dépendante lorsque la variable indépendante est
égale à zéro. Le coefficient de
régression représente la variation moyenne de la
variable dépendante pour une augmentation d’une unité de la variable
indépendante (autrement dit, la pente).
| Information | Description |
|---|---|
| Formule | Notre modèle linéaire (variable dépendante ~ variable indépendante) |
| Résidus | Différence entre la valeur observée et la valeur prédite de la variable dépendante |
| Ordonnée à l’origine | Valeur prédite de la variable dépendante lorsque la variable indépendante est égale à zéro |
| Coefficient | Variation moyenne de la variable dépendante pour une augmentation d’une unité de la variable indépendante |
| Valeur p | Probabilité d’obtenir un coefficient semblable au vôtre (ou plus extrême) si l’hypothèse nulle (= aucune relation entre la VD et la VI) est vraie |
| Degrés de liberté | Nombre d’observations − nombre de variables indépendantes − 1 |
| R2 | Proportion de la variance de la variable dépendante expliquée par le modèle |
À noter : lm() retire automatiquement
toutes les lignes qui contiennent une valeur manquante dans l’une des
variables du modèle (listwise deletion). Autrement dit, seules
les observations complètes sont utilisées. Le jeu de données
swiss ne contient aucune valeur manquante, mais ce ne
sera pas toujours le cas!
# Estimer notre modèle avec lm()
modele1 <- lm(Fertility ~ Infant.Mortality, data=swiss)
# Afficher les résultats de la régression avec summary()
summary(modele1)
##
## Call:
## lm(formula = Fertility ~ Infant.Mortality, data = swiss)
##
## Residuals:
## Min 1Q Median 3Q Max
## -31.672 -5.687 -0.381 7.239 28.565
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 34.5155 11.7113 2.947 0.00507 **
## Infant.Mortality 1.7865 0.5812 3.074 0.00359 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 11.48 on 45 degrees of freedom
## Multiple R-squared: 0.1735, Adjusted R-squared: 0.1552
## F-statistic: 9.448 on 1 and 45 DF, p-value: 0.003585
Comment lire ce résultat?
- L’ordonnée à l’origine (Intercept = 34,52) : une province dont la mortalité infantile serait de 0 % aurait un indice de fécondité prédit de 34,52. Attention : aucune province n’a une mortalité infantile près de 0 % (le minimum est de 10,8 %). Il s’agit donc d’une extrapolation hors de nos données, qui n’a pas vraiment de sens substantiel.
- Le coefficient (Infant.Mortality = 1,79) : chaque point de pourcentage supplémentaire de mortalité infantile est associé, en moyenne, à un indice de fécondité plus élevé de 1,79 point. La relation est positive.
- La valeur p (≈ 0,0036) : si la mortalité infantile n’avait aucun lien avec la fécondité, il n’y aurait qu’environ 0,36 % de chances d’observer un coefficient aussi éloigné de zéro (ou plus) par le seul fait du hasard. Comme p < 0,05, on rejette l’hypothèse nulle : la relation est statistiquement significative.
- Le R2 (Multiple R-squared = 0,17) : la mortalité infantile explique environ 17 % de la variance de la fécondité entre les provinces. Autrement dit, environ 83 % de la variation reste inexpliquée par ce modèle. (PAS À L’EXAMEN)
- Les degrés de liberté (45) : 47 provinces − 1 variable indépendante − 1 = 45. (PAS À L’EXAMEN)
Pour donner un sens concret au coefficient : comparons une province où la mortalité infantile est de 15 % à une province où elle est de 25 %. La différence prédite de fécondité est de 10 × 1,79 ≈ 17,9 points, soit plus d’un écart-type de la variable dépendante (environ 12,5). L’effet est donc loin d’être négligeable.
Visualisons maintenant les résultats de modele1 dans un graphique.
# Nuage de points avec la droite de régression
ggplot(data=swiss, aes(Infant.Mortality, Fertility)) +
geom_point() +
xlab("Mortalité infantile (%)") + ylab("Indice de fécondité") +
theme_minimal(base_size = 20) +
geom_smooth(method='lm', formula= y~x) + # Cette ligne ajoute la droite de régression
xlim(0,30)
La droite bleue représente les valeurs prédites par notre modèle. La zone grise autour de la droite représente l’intervalle de confiance à 95 % de la prédiction. Remarquez qu’elle s’élargit aux extrémités, là où nous avons moins d’observations.
2.3 Les modèles polynomiaux
Note sur les modèles polynomiaux (facultatif)
Parfois, la relation entre x et y est mieux décrite par une fonction polynomiale de degré n. Ainsi, au lieu de :
\[Y_i = \beta_0 + \beta_1x_i + \epsilon_i\]
on pourrait avoir :
\[Y_i = \beta_0 + \beta_1x_i + \beta_2x_i^2 + \epsilon_i\]
où x prend une forme polynomiale (\(x^2\) correspond à un polynôme de degré 2, \(x^3\) à un polynôme de degré 3, et ainsi de suite). Ce type de modèle permet à la relation de « courber ».
Une courbe LOESS (locally estimated scatterplot smoothing) estime une multitude de petites régressions locales à travers les données. Elle fait ressortir les tendances dans la relation Y ~ X sans imposer de forme particulière. C’est un outil très utile pour explorer visuellement des relations plus nuancées.
On peut se tourner vers un modèle polynomial lorsque la relation entre nos variables n’est manifestement pas linéaire. Notez que les modèles polynomiaux sont techniquement encore des modèles linéaires (ils sont linéaires dans leurs paramètres β), mais nous n’irons pas plus loin sur ce point dans ce cours.
### LOESS ###
ggplot(data=swiss, aes(Infant.Mortality, Fertility)) +
geom_point() +
xlab("Mortalité infantile (%)") + ylab("Indice de fécondité") +
theme_minimal(base_size = 20) +
geom_smooth(method='loess', formula= y~x) + # Cette ligne ajoute la courbe LOESS
xlim(0,30)
### Modèle polynomial (degré 2) ###
ggplot(data=swiss, aes(Infant.Mortality, Fertility)) +
geom_point() +
xlab("Mortalité infantile (%)") + ylab("Indice de fécondité") +
theme_minimal(base_size = 20) +
geom_smooth(method='lm', formula=y~poly(x,2)) + # Cette ligne ajoute la courbe polynomiale
xlim(0,30)
Comment lire ces graphiques? Dans les deux cas, la courbe reste globalement croissante : la fécondité tend à augmenter avec la mortalité infantile. La courbure observée est surtout due à quelques provinces situées aux extrémités (où les intervalles de confiance sont très larges). Rien n’indique donc qu’une simple droite soit inadéquate pour résumer cette relation.
3. Les résidus
Les résidus représentent la valeur observée moins la valeur prédite par le modèle. Chaque observation (chaque point du nuage) a son propre résidu : c’est la distance verticale entre le point et la droite de régression.
# Ajouter les résultats du modèle à nos données dans un nouveau data frame
swiss_avecInfoLm <- augment(modele1) # Cette ligne de code n'est pas sujet à évaluation
# Visualiser les résidus
ggplot(swiss_avecInfoLm, aes(Infant.Mortality, Fertility)) +
geom_point() +
xlab("Mortalité infantile (%)") + ylab("Indice de fécondité") +
geom_smooth(method = 'lm', formula = y~x, se = FALSE) +
geom_segment(aes(xend = Infant.Mortality, yend = .fitted), color = "red", linewidth = 0.3) +
theme_minimal(base_size = 20) +
xlim(0,30)
# L'important ici c'est de comprendre la visualisation, pas le code qui la crée
4. Relations multivariées
En analyse de données, on utilise souvent des modèles de régression linéaire multiple : variable dépendante ~ variable indépendante 1 + variable indépendante 2. La différence principale avec la régression simple est que le modèle contient plus d’une variable indépendante (ou prédicteur).
# Estimer notre modèle avec lm()
modele2 <- lm(Fertility ~ Infant.Mortality + Education, data=swiss)
# Afficher les résultats de la régression avec summary()
summary(modele2)
##
## Call:
## lm(formula = Fertility ~ Infant.Mortality + Education, data = swiss)
##
## Residuals:
## Min 1Q Median 3Q Max
## -15.3906 -6.0088 -0.9624 5.8808 21.0736
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 48.8213 8.8904 5.491 1.88e-06 ***
## Infant.Mortality 1.5187 0.4287 3.543 0.000951 ***
## Education -0.8167 0.1298 -6.289 1.27e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 8.426 on 44 degrees of freedom
## Multiple R-squared: 0.5648, Adjusted R-squared: 0.545
## F-statistic: 28.55 on 2 and 44 DF, p-value: 1.126e-08
Comment lire ce résultat?
- Mortalité infantile (1,52; p ≈ 0,001) : à niveau de scolarité égal, chaque point de pourcentage supplémentaire de mortalité infantile est associé, en moyenne, à un indice de fécondité plus élevé de 1,52 point. La relation reste positive et statistiquement significative.
- Scolarité (−0,82; p ≈ 0,0000001) : à mortalité infantile égale, chaque point de pourcentage supplémentaire de conscrits ayant dépassé le primaire est associé, en moyenne, à un indice de fécondité plus faible de 0,82 point. La relation est négative et très significative.
- Le R2 (0,56) : ensemble, les deux variables expliquent environ 56 % de la variance de la fécondité, contre 17 % pour la mortalité infantile seule. Le R2 ajusté (0,545) confirme que l’ajout de la scolarité améliore réellement le modèle. (PAS À L’EXAMEN)
- L’ordonnée à l’origine (48,82) : fécondité prédite pour une province où la mortalité infantile et la scolarité seraient de 0 %. Encore une fois, c’est une extrapolation sans grande signification.
« Toutes choses égales par ailleurs » : dans une régression multiple, chaque coefficient s’interprète en maintenant les autres variables du modèle constantes. C’est ce qu’on appelle contrôler pour une variable.
Visuellement, une régression à deux variables indépendantes ne prend plus la forme d’une droite, mais d’un plan.
Le plan monte dans la direction de la mortalité infantile (coefficient positif) et descend dans la direction de la scolarité (coefficient négatif). Faites pivoter le graphique avec la souris : la distance verticale entre chaque point et le plan est, encore une fois, le résidu de cette province. Survolez un point pour voir de quelle province il s’agit.
5. Exercices
Les solutions sont cachées par défaut : cliquez sur le bouton « Voir la solution » seulement après avoir essayé par vous-même!
Exercice 1
À l’aide de ggplot(), représentez graphiquement un
modèle MCO où le % d’hommes travaillant en agriculture
est utilisé pour prédire la fécondité, puis une courbe
LOESS pour la même relation. La relation semble-t-elle linéaire?
Voir la solution
# Solution
ggplot(data=swiss, aes(Agriculture, Fertility)) +
geom_point() +
xlab("Agriculture (%)") + ylab("Indice de fécondité") +
theme_minimal(base_size = 20) +
geom_smooth(method='lm', formula= y~x) # Droite de régression
ggplot(data=swiss, aes(Agriculture, Fertility)) +
geom_point() +
xlab("Agriculture (%)") + ylab("Indice de fécondité") +
theme_minimal(base_size = 20) +
geom_smooth(method='loess', formula= y~x) # Courbe LOESS
# La droite indique une relation positive, mais assez faible : les points
# sont très dispersés autour de la droite. La courbe LOESS reste
# globalement croissante, sans courbure marquée.
Exercice 2
À l’aide de lm(), estimez un modèle MCO où le %
d’hommes travaillant en agriculture et le % de
scolarité sont utilisés pour prédire la
fécondité. Interprétez vos coefficients de régression,
les valeurs p associées et le R2.
Voir la solution
# Solution
modele3 <- lm(Fertility ~ Agriculture + Education, data=swiss)
summary(modele3)
##
## Call:
## lm(formula = Fertility ~ Agriculture + Education, data = swiss)
##
## Residuals:
## Min 1Q Median 3Q Max
## -17.3072 -6.6157 -0.9443 8.7028 20.5291
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 84.08005 5.78180 14.542 < 2e-16 ***
## Agriculture -0.06648 0.08005 -0.830 0.411
## Education -0.96276 0.18906 -5.092 7.1e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 9.479 on 44 degrees of freedom
## Multiple R-squared: 0.4492, Adjusted R-squared: 0.4242
## F-statistic: 17.95 on 2 and 44 DF, p-value: 2e-06
# Agriculture (-0,066) : à scolarité égale, chaque point de pourcentage
# supplémentaire d'hommes en agriculture est associé à une baisse moyenne
# de 0,066 point de l'indice de fécondité. Mais la valeur p (environ 0,41)
# est supérieure à 0,05 : on ne rejette pas l'hypothèse nulle. La relation
# n'est pas statistiquement significative.
# Scolarité (-0,96) : à agriculture égale, chaque point de pourcentage
# supplémentaire de scolarité est associé à une baisse moyenne de 0,96 point
# de l'indice de fécondité. La valeur p (environ 0,000007) est bien
# inférieure à 0,05 : la relation est statistiquement significative.
# R2 (0,45) : ensemble, les deux variables expliquent environ 45 % de la
# variance de la fécondité.
Exercice 3
(a) Estimez un modèle de régression simple où seul le % d’hommes travaillant en agriculture prédit la fécondité. Comparez le coefficient de l’agriculture avec celui de l’exercice 2. Que remarquez-vous? Comment l’expliquer?
Indice : pensez à la relation entre l’agriculture et la
scolarité. Vous pouvez utiliser
cor(swiss$Agriculture, swiss$Education).
(b) Sans utiliser R : à partir du modèle 2 (section 4), un collègue conclut que « si l’on augmente la scolarité d’une personne, elle aura moins d’enfants ». Sa conclusion est-elle correcte?
Voir la solution
# Solution (a)
modele4 <- lm(Fertility ~ Agriculture, data=swiss)
summary(modele4)
##
## Call:
## lm(formula = Fertility ~ Agriculture, data = swiss)
##
## Residuals:
## Min 1Q Median 3Q Max
## -25.5374 -7.8685 -0.6362 9.0464 24.4858
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 60.30438 4.25126 14.185 <2e-16 ***
## Agriculture 0.19420 0.07671 2.532 0.0149 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 11.82 on 45 degrees of freedom
## Multiple R-squared: 0.1247, Adjusted R-squared: 0.1052
## F-statistic: 6.409 on 1 and 45 DF, p-value: 0.01492
cor(swiss$Agriculture, swiss$Education)
## [1] -0.6395225
# Seule, l'agriculture a un coefficient POSITIF (environ 0,19) et
# statistiquement significatif (p environ 0,015). Une fois qu'on contrôle
# pour la scolarité (exercice 2), le coefficient devient légèrement négatif
# (-0,066) et n'est plus significatif (p environ 0,41).
# Explication : les provinces agricoles sont beaucoup moins scolarisées
# (corrélation d'environ -0,64). Dans le modèle simple, l'agriculture
# « capte » en partie l'effet de la scolarité : c'est un biais de variable
# omise. À scolarité égale, l'agriculture n'est plus liée à la fécondité.
# Solution (b)
# Non, pour deux raisons :
# 1) Corrélation n'est pas causalité : le modèle montre une association,
# pas un effet causal (des variables omises pourraient expliquer la
# relation).
# 2) Sophisme écologique : les données portent sur des provinces, pas sur
# des personnes. On ne peut pas tirer de conclusion sur le comportement
# individuel à partir de données agrégées.