17  Régression linéaire : comprendre ce qui change après ajustement

ImportantQuestion de départ

Le gradient de satisfaction de vie observé selon le diplôme reste-t-il du même ordre de grandeur lorsque l’on tient compte de l’âge, du sexe, de l’emploi, du revenu et de la santé ?

17.1 Objectifs d’apprentissage

À la fin de ce chapitre, vous saurez :

  • interpréter un coefficient de régression linéaire dans son unité substantive ;
  • lire une variable catégorielle par rapport à sa référence ;
  • construire des modèles emboîtés guidés par une question ;
  • utiliser svyglm() pour tenir compte du plan ;
  • comparer une association brute et une association ajustée ;
  • produire un tableau de modèles avec {gtsummary} ;
  • communiquer des prédictions ajustées ;
  • distinguer atténuation statistique, médiation et causalité.

17.2 Pourquoi modéliser après les descriptifs ?

Le chapitre 11 a montré une satisfaction moyenne légèrement plus élevée dans les catégories de diplôme supérieures. Mais les groupes scolaires diffèrent aussi par l’âge, le revenu, la santé et d’autres caractéristiques.

Une régression linéaire décrit l’espérance conditionnelle :

\[ E(Y|X) = \beta_0 + \beta_1 X_1 + \cdots + \beta_p X_p. \]

Un coefficient indique comment varie la moyenne conditionnelle de \(Y\) lorsque la variable considérée change, pour les valeurs données des autres variables incluses dans le modèle.

AvertissementAjusté ne signifie pas causal

« Toutes choses égales par ailleurs dans le modèle » signifie seulement que les variables incluses sont maintenues constantes statistiquement. Cela ne garantit ni absence de confusion résiduelle, ni temporalité correcte, ni absence de médiateurs ou de biais de sélection.

17.3 Avant de comparer des modèles : garder le même échantillon

Un piège classique consiste à comparer deux coefficients alors que l’ajout d’une variable a aussi supprimé des observations. On ne sait plus si le coefficient change à cause de l’ajustement ou parce que l’échantillon n’est plus le même.

Pour suivre proprement M1 à M4, nous définissons donc une seule fois l’échantillon complet sur toutes les variables du modèle final, puis nous réestimons chaque spécification sur ce même domaine.

Afficher le code R
design_reg <- subset(
  design,
  !is.na(satisfaction_vie) &
    !is.na(diplome_4) &
    !is.na(age) &
    !is.na(sexe_f) &
    !is.na(en_emploi) &
    !is.na(revenu_k) &
    !is.na(sante_f)
)

n_reg <- nrow(design_reg$variables)

Le parcours de modèles porte ainsi sur 3 050 observations à chaque étape. Les descriptifs du chapitre 11, eux, utilisaient toute l’information disponible variable par variable : les deux stratégies répondent à des objectifs différents.

17.4 Étape 1 — association brute diplôme–satisfaction

Afficher le code R
m1 <- survey::svyglm(
  satisfaction_vie ~ diplome_4,
  design = design_reg
)

Avec « Inférieur au bac » comme référence, les coefficients des autres catégories sont des différences de satisfaction moyenne par rapport à ce groupe.

17.5 Étape 2 — composition démographique

Afficher le code R
m2 <- survey::svyglm(
  satisfaction_vie ~ diplome_4 + age + sexe_f,
  design = design_reg
)

Le coefficient d’âge est exprimé pour une année. Si cette unité paraît trop fine, on pourrait exprimer l’âge en décennies ou centrer l’âge autour de 45 ans.

17.6 Étape 3 — ressources économiques et situation d’emploi

Le revenu est exprimé en milliers d’euros dans revenu_k, variable construite avant la création du design.

Afficher le code R
m3 <- survey::svyglm(
  satisfaction_vie ~ diplome_4 + age + sexe_f + en_emploi + revenu_k,
  design = design_reg
)

Le coefficient de revenu_k s’interprète alors comme la différence moyenne de satisfaction associée à 1 000 € de revenu mensuel supplémentaires, à valeurs égales des autres variables du modèle.

17.7 Étape 4 — ajouter l’état de santé

Afficher le code R
m4 <- survey::svyglm(
  satisfaction_vie ~ diplome_4 + age + sexe_f + en_emploi + revenu_k + sante_f,
  design = design_reg
)

L’état de santé est très fortement lié au bien-être déclaré. Son ajout permet ici de demander si le gradient scolaire reste visible à santé déclarée comparable.

17.8 Suivre le contraste principal sans noyer le lecteur

Pour la comparaison des modèles, nous suivons un seul contraste : « supérieur long » versus « inférieur au bac ». L’objectif n’est pas de masquer les autres coefficients — le tableau final les donnera — mais de visualiser ce qui arrive à l’association qui motive la séquence.

Afficher le code R
resume_contraste <- function(modele, nom_modele) {
  terme <- grep("Supérieur long", names(stats::coef(modele)), value = TRUE)[1]
  ci <- stats::confint(modele)[terme, ]
  tibble::tibble(
    Modèle = nom_modele,
    beta = as.numeric(stats::coef(modele)[terme]),
    bas = as.numeric(ci[1]),
    haut = as.numeric(ci[2])
  )
}

progression <- dplyr::bind_rows(
  resume_contraste(m1, "M1 · diplôme"),
  resume_contraste(m2, "M2 · + âge, sexe"),
  resume_contraste(m3, "M3 · + emploi, revenu"),
  resume_contraste(m4, "M4 · + santé")
) |>
  dplyr::mutate(Modèle = factor(Modèle, levels = Modèle))

knitr::kable(
  progression |>
    dplyr::transmute(
      Spécification = Modèle,
      `β supérieur long vs inférieur au bac` = fmt_num(beta, .01),
      `IC 95 %` = paste0("[", fmt_num(bas, .01), " ; ", fmt_num(haut, .01), "]")
    ),
  align = c("l", "r", "c")
)
Spécification β supérieur long vs inférieur au bac IC 95 %
M1 · diplôme 0,43 [0,25 ; 0,60]
M2 · + âge, sexe 0,34 [0,16 ; 0,52]
M3 · + emploi, revenu 0,03 [-0,17 ; 0,23]
M4 · + santé 0,05 [-0,14 ; 0,24]
Afficher le code R
ggplot(progression, aes(x = beta, y = forcats::fct_rev(Modèle))) +
  geom_vline(xintercept = 0, linetype = 2, colour = couleurs_enqueter[["gris"]]) +
  geom_errorbarh(
    aes(xmin = bas, xmax = haut),
    height = .10, linewidth = .65,
    colour = couleurs_enqueter[["gris"]]
  ) +
  geom_point(size = 3, colour = couleurs_enqueter[["principal"]]) +
  labs(
    x = "Différence de satisfaction (points, IC 95 %)",
    y = NULL,
    title = "Le gradient scolaire s'atténue surtout après l'introduction des ressources économiques",
    subtitle = "Même échantillon analytique dans les quatre spécifications",
    caption = "Contraste : supérieur long versus inférieur au bac ; données synthétiques EnquêteR."
  ) +
  theme_enqueter()

Le coefficient associé au diplôme supérieur long diminue fortement lorsque l'emploi et le revenu sont ajoutés, puis change peu après ajout de la santé.

Sur ce même échantillon, l’écart entre les deux extrêmes du diplôme est d’environ 0,43 point dans M1. Il tombe à 0,03 dans M3 et reste proche de 0,05 dans M4. L’essentiel de l’atténuation se produit donc au moment où l’emploi et le revenu entrent dans le modèle.

Cette lecture est plus solide que la comparaison de quatre sorties indépendantes : comme le nombre d’observations est fixé, la trajectoire du coefficient reflète bien le changement de spécification, et non un mélange de spécification et de sélection des cas complets.

NoteLecture sociologique

Dans une enquête réelle, cette atténuation orienterait l’interprétation vers les ressources et positions sociales associées au diplôme plutôt que vers une relation autonome entre titre scolaire et bien-être. Ici, revenu et emploi captent une partie de ces différences ; la santé en modifie peu davantage le contraste scolaire. Cela ne suffit pas à établir une chaîne causale, mais cela aide à formuler plus précisément ce que le modèle rend plausible.

AvertissementAtténuation ≠ médiation démontrée

Dire que « le revenu explique l’effet du diplôme » serait trop fort. Dans une coupe transversale, revenu, emploi, santé et diplôme peuvent être liés par plusieurs chemins causaux et processus de sélection. La séquence M1–M4 est une décomposition descriptive conditionnelle, pas une analyse de médiation.

17.9 Tableau final du modèle ajusté

Tableau 17.2. Associations ajustées avec la satisfaction de vie

Afficher le code R
tbl_m4 <- tbl_regression(
  m4,
  intercept = FALSE,
  label = list(
    diplome_4 ~ "Niveau de diplôme",
    age ~ "Âge (années)",
    sexe_f ~ "Sexe / genre",
    en_emploi ~ "En emploi",
    revenu_k ~ "Revenu mensuel (+1 000 €)",
    sante_f ~ "État de santé déclaré"
  )
) |>
  bold_labels()

tbl_m4
Caractéristique Beta 95% IC p-valeur
Niveau de diplôme


    Inférieur au bac
    Bac 0,12 -0,03 – 0,27 0,10
    Bac+2 0,15 -0,01 – 0,30 0,061
    Supérieur long 0,05 -0,14 – 0,24 0,6
Âge (années) 0,00 0,00 – 0,00 0,8
Sexe / genre


    Homme
    Femme 0,03 -0,06 – 0,12 0,5
    Autre / non-binaire 0,00 -0,44 – 0,44 >0,9
En emploi 0,06 -0,09 – 0,21 0,5
Revenu mensuel (+1 000 €) 0,29 0,18 – 0,39 <0,001
État de santé déclaré


    Très bonne
    Bonne -0,40 -0,58 – -0,22 <0,001
    Moyenne -0,85 -1,0 – -0,67 <0,001
    Mauvaise -1,4 -1,7 – -1,1 <0,001
    Très mauvaise -2,2 -3,0 – -1,3 <0,001
Abréviation: IC = intervalle de confiance

Le tableau doit être lu en unités originales : points de satisfaction sur une échelle 0–10. Une différence de 0,1 ou 0,3 point doit être jugée sur cette échelle, pas seulement via sa valeur-p.

Pour une variable catégorielle à quatre modalités, trois coefficients séparés ne répondent pas à la question « le diplôme est-il associé globalement au résultat ? ». Un test conjoint est plus approprié :

Afficher le code R
test_diplome_m4 <- survey::regTermTest(m4, ~diplome_4)

tibble::tibble(
  Terme = "Niveau de diplôme — test global",
  `Valeur-p` = fmt_p(test_diplome_m4$p)
) |>
  knitr::kable(align = c("l", "r"))
Terme Valeur-p
Niveau de diplôme — test global 0,209

Ce test complète les coefficients ; il ne remplace ni leur ordre de grandeur ni les prédictions ci-dessous.

17.10 Prédictions : revenir à une échelle directement lisible

Comparons quatre profils identiques sauf pour le diplôme : 45 ans, femme, en emploi, revenu de 2 200 €, santé bonne.

Afficher le code R
profils_sat <- tibble(
  diplome_4 = factor(
    levels(enqueter$diplome_4),
    levels = levels(enqueter$diplome_4)
  ),
  age = 45,
  sexe_f = factor("Femme", levels = levels(enqueter$sexe_f)),
  en_emploi = 1,
  revenu_k = 2.2,
  sante_f = factor("Bonne", levels = levels(enqueter$sante_f))
)

pred_sat <- predict(m4, newdata = profils_sat, se.fit = TRUE)

pred_sat_ci <- ci_design(
  est = as.numeric(coef(pred_sat)),
  se = as.numeric(SE(pred_sat)),
  design = design_reg
)

pred_sat_df <- profils_sat |>
  mutate(
    prediction = as.numeric(coef(pred_sat)),
    se = as.numeric(SE(pred_sat)),
    bas = pred_sat_ci[, "bas"],
    haut = pred_sat_ci[, "haut"]
  )
Afficher le code R
ggplot(pred_sat_df, aes(x = prediction, y = diplome_4)) +
  geom_errorbarh(
    aes(xmin = bas, xmax = haut),
    height = .12,
    colour = couleurs_enqueter[["gris"]]
  ) +
  geom_point(size = 3.2, colour = couleurs_enqueter[["principal"]]) +
  scale_x_continuous(limits = c(5.5, 8.5)) +
  labs(
    x = "Satisfaction moyenne prédite (0–10, IC 95 %)",
    y = NULL,
    title = "Après ajustement, le gradient scolaire de satisfaction devient faible",
    subtitle = "Profil : 45 ans, femme, en emploi, revenu 2 200 €, santé bonne",
    caption = "Intervalles pour la moyenne conditionnelle prédite, fondés sur les degrés de liberté du plan ; données synthétiques."
  ) +
  theme_enqueter()

Les prédictions ajustées de satisfaction sont proches entre niveaux de diplôme après contrôle du revenu, de l'emploi, de l'âge, du sexe et de la santé.

Cette figure est souvent plus parlante que quatre coefficients : elle montre directement la petite amplitude résiduelle du contraste scolaire lorsque le profil est fixé.

17.11 Forme fonctionnelle : l’âge n’est pas toujours linéaire

Une inspection graphique précède le choix de la forme :

Afficher le code R
ggplot(enqueter, aes(age, satisfaction_vie, weight = poids_final)) +
  geom_jitter(alpha = .08, width = .2, height = .05, na.rm = TRUE) +
  geom_smooth(
    method = "loess",
    se = TRUE,
    colour = couleurs_enqueter[["principal"]],
    fill = couleurs_enqueter[["gris_clair"]],
    na.rm = TRUE
  ) +
  labs(
    x = "Âge",
    y = "Satisfaction de vie",
    title = "Inspecter la forme avant d'imposer une droite",
    subtitle = "Lissage descriptif pondéré par le poids final"
  ) +
  theme_enqueter()

Si une courbure paraît substantielle, on peut comparer une spécification avec terme quadratique ou spline. Les coefficients age et age² deviennent alors difficiles à lire isolément ; on privilégie les prédictions.

17.12 Cas complets : l’échantillon du modèle est aussi un résultat

Afficher le code R
tibble::tibble(
  Étape = c("Fichier analytique", "Échantillon commun M1–M4", "Observations écartées"),
  N = c(nrow(enqueter), n_reg, nrow(enqueter) - n_reg)
) |>
  knitr::kable(align = c("l", "r"))
Étape N
Fichier analytique 3592
Échantillon commun M1–M4 3050
Observations écartées 542

Le revenu explique une grande partie de la réduction d’effectif. C’est précisément pourquoi nous avons fixé l’échantillon avant de comparer les modèles. Le chapitre 21 reviendra sur cette sélection par cas complets et montrera comment l’imputation multiple peut être utilisée comme analyse de sensibilité.

17.13 Mini-exercice

Si le coefficient de revenu_k vaut 0,30, comment l’interpréter ?

À caractéristiques incluses dans le modèle comparables, 1 000 € de revenu mensuel supplémentaires sont associés à environ 0,30 point supplémentaire de satisfaction de vie. Cette formulation reste associationnelle.

17.14 Exercice de synthèse

17.14.1 Niveau A — Appliquer

Reproduisez M1 à M4 et vérifiez comment évoluent les coefficients du diplôme.

17.14.2 Niveau B — Choisir

Proposez une autre séquence de modèles et justifiez l’ordre d’introduction des variables en termes substantifs, non en fonction de leurs valeurs-p.

17.14.3 Niveau C — Analyser

Rédigez 200 mots répondant à : « Le diplôme est-il associé à la satisfaction de vie ? ». Votre texte doit distinguer descriptif brut, association ajustée, rôle possible du revenu et de la santé, et limites causales.

17.15 À retenir

  • Un coefficient de régression linéaire décrit une différence moyenne conditionnelle.
  • Les catégories de référence et unités déterminent l’interprétation.
  • Les modèles emboîtés permettent de suivre la stabilité d’une association principale.
  • Une forte atténuation après ajustement est substantiellement intéressante, mais ne démontre pas une médiation causale.
  • svyglm() utilise le plan d’enquête pour l’inférence (Lumley et al. 2026).
  • Les prédictions ajustées traduisent les coefficients dans une échelle plus directement communicable.
  • L’échantillon des cas complets doit être documenté.

17.16 Pour aller plus loin

Le chapitre suivant traite une réponse binaire. Nous en profiterons pour montrer qu’une bonne régression logistique commence par définir correctement l’univers analytique avant de calculer des odds ratios.