13  Produire des tableaux de résultats lisibles et défendables

ImportantQuestion de départ

Comment construire un tableau qui permette au lecteur de comprendre immédiatement qui est décrit, quel dénominateur est utilisé, ce qui est pondéré et quelle incertitude accompagne le résultat ?

13.1 Objectifs d’apprentissage

À la fin de ce chapitre, vous saurez :

  • distinguer tableau de diagnostic, tableau analytique et tableau de publication ;
  • séparer effectifs observés et estimations pondérées ;
  • utiliser tbl_summary() et tbl_svysummary() sans perdre le sens du design ;
  • afficher les valeurs manquantes lorsque leur présence modifie l’interprétation ;
  • choisir un dénominateur explicite ;
  • sélectionner les statistiques réellement utiles au lieu d’imprimer une sortie exhaustive ;
  • présenter les intervalles de confiance lorsqu’ils font partie du message ;
  • construire un tableau de régression qui privilégie les contrastes interprétables.

13.2 Un tableau a une fonction avant d’avoir un style

Trois usages doivent être distingués.

Type de tableau Fonction Contenu typique À éviter
Diagnostic contrôler les données N, manquants, modalités rares, bornes mise en forme sophistiquée
Analytique comprendre un résultat estimations, comparaisons, IC multiplier les décimales
Publication transmettre un message variables sélectionnées, labels, notes, unités recopier toute la console R

Un tableau devient difficile à lire lorsqu’il essaie de remplir les trois fonctions à la fois.

AstucePrincipe éditorial

Avant de produire un tableau, écrivez en une phrase la question à laquelle il doit répondre. Si aucune phrase claire ne vient, le tableau n’est probablement pas encore défini.

13.3 Diagnostic : les valeurs manquantes et les dénominateurs d’abord

Afficher le code R
diagnostic <- tibble::tibble(
  Variable = c("Âge", "Diplôme", "Revenu", "Sport", "Satisfaction"),
  `N total` = nrow(enqueter),
  `N disponible` = c(
    sum(!is.na(enqueter$age)),
    sum(!is.na(enqueter$diplome_4)),
    sum(!is.na(enqueter$revenu_mensuel)),
    sum(!is.na(enqueter$sport_regulier)),
    sum(!is.na(enqueter$satisfaction_vie))
  ),
  `N manquant` = c(
    sum(is.na(enqueter$age)),
    sum(is.na(enqueter$diplome_4)),
    sum(is.na(enqueter$revenu_mensuel)),
    sum(is.na(enqueter$sport_regulier)),
    sum(is.na(enqueter$satisfaction_vie))
  )
) |>
  mutate(`% manquant` = fmt_pct(`N manquant` / `N total`, .1))

knitr::kable(diagnostic, align = c("l", "r", "r", "r", "r"))
Variable N total N disponible N manquant % manquant
Âge 3592 3568 24 0,7%
Diplôme 3592 3528 64 1,8%
Revenu 3592 3266 326 9,1%
Sport 3592 3540 52 1,4%
Satisfaction 3592 3543 49 1,4%

Ce tableau n’est pas destiné à une publication finale. Il sert à empêcher une erreur fréquente : comparer des statistiques dont les dénominateurs réels diffèrent sans s’en apercevoir.

13.4 tbl_summary() et tbl_svysummary() ne répondent pas à la même question

tbl_summary() travaille sur un tableau de données ordinaire. Il décrit les observations. tbl_svysummary() travaille sur un objet de plan et permet d’obtenir des statistiques pondérées tenant compte du design (Sjoberg et al. 2021; Lumley et al. 2026).

13.4.1 Un premier tableau brut

Afficher le code R
enqueter |>
  select(age, sexe_f, diplome_4, revenu_mensuel, sport_regulier_f) |>
  tbl_summary(
    statistic = list(
      all_continuous() ~ "{median} ({p25}–{p75})",
      all_categorical() ~ "{n} ({p}%)"
    ),
    missing = "ifany",
    label = list(
      age ~ "Âge (ans)",
      sexe_f ~ "Sexe / genre",
      diplome_4 ~ "Niveau de diplôme",
      revenu_mensuel ~ "Revenu mensuel net (€)",
      sport_regulier_f ~ "Sport au moins hebdomadaire"
    )
  ) |>
  bold_labels()
Caractéristique N = 3 5921
Âge (ans) 46 (35–57)
    Manquant 24
Sexe / genre
    Homme 1 692 (48%)
    Femme 1 814 (51%)
    Autre / non-binaire 54 (1,5%)
    Manquant 32
Niveau de diplôme
    Inférieur au bac 1 601 (45%)
    Bac 703 (20%)
    Bac+2 548 (16%)
    Supérieur long 676 (19%)
    Manquant 64
Revenu mensuel net (€) 2 250 (1 700–2 750)
    Manquant 326
Sport au moins hebdomadaire
    Non 2 408 (68%)
    Oui 1 132 (32%)
    Manquant 52
1 Médiane (Q1–Q3); n (%)

Ce tableau répond à une question descriptive simple : à quoi ressemble l’échantillon observé ? Il ne doit pas être présenté comme une table d’estimations de population.

13.5 Une Table 1 d’enquête : N observé et statistique pondérée

Dans un rapport fondé sur un plan complexe, le lecteur a souvent besoin de deux informations différentes : le nombre de personnes réellement observées et l’estimation pondérée. Il est préférable de les afficher explicitement plutôt que de laisser croire qu’un « N pondéré » correspond à un nombre de personnes enquêtées.

Afficher le code R
# Les N non pondérés sont calculés sur le fichier.
n_unweighted <- enqueter |>
  summarise(
    `N âge` = sum(!is.na(age)),
    `N revenu` = sum(!is.na(revenu_mensuel)),
    `N satisfaction` = sum(!is.na(satisfaction_vie)),
    `N sport` = sum(!is.na(sport_regulier))
  )

# Les statistiques centrales sont estimées avec le design.
table1_svy <- design |>
  tbl_svysummary(
    include = c(age, sexe_f, diplome_4, revenu_mensuel, satisfaction_vie, sport_regulier),
    statistic = list(
      age ~ "{mean} (SE {mean.std.error})",
      revenu_mensuel ~ "{median} ({p25}–{p75})",
      satisfaction_vie ~ "{mean} (SE {mean.std.error})",
      all_categorical() ~ "{p}%",
      sport_regulier ~ "{p}%"
    ),
    type = list(
      sport_regulier ~ "dichotomous"
    ),
    missing = "ifany",
    label = list(
      age ~ "Âge (ans)",
      sexe_f ~ "Sexe / genre",
      diplome_4 ~ "Niveau de diplôme",
      revenu_mensuel ~ "Revenu mensuel net (€)",
      satisfaction_vie ~ "Satisfaction de vie (0–10)",
      sport_regulier ~ "Sport au moins hebdomadaire"
    )
  ) |>
  bold_labels()

table1_svy
Caractéristique N = 3 5931
Âge (ans) 46 (SE 0)
    Manquant 24
Sexe / genre
    Homme 49%
    Femme 50%
    Autre / non-binaire 1,4%
    Manquant 34
Niveau de diplôme
    Inférieur au bac 46%
    Bac 20%
    Bac+2 15%
    Supérieur long 19%
    Manquant 66
Revenu mensuel net (€) 2 250 (1 700–2 750)
    Manquant 334
Satisfaction de vie (0–10) 6,81 (SE 0,03)
    Manquant 50
Sport au moins hebdomadaire 32%
    Manquant 56
1 Moyenne (SE ET); %; Médiane (Q1–Q3)

Le tableau pondéré n’a pas vocation à remplacer la documentation du N. Dans un article, une note simple peut préciser :

Les effectifs sont non pondérés ; les pourcentages, moyennes et erreurs standards tiennent compte du plan d’enquête. Les dénominateurs varient selon les données disponibles.

Cette phrase évite une ambiguïté beaucoup plus importante qu’une différence de police ou de bordure.

13.6 Un tableau comparatif doit avoir un axe substantiel

Le diplôme constitue ici l’axe de comparaison. Au lieu d’empiler une dizaine de variables, sélectionnons celles qui décrivent réellement un gradient de ressources et de pratiques.

Afficher le code R
design |>
  tbl_svysummary(
    by = diplome_4,
    include = c(
      revenu_mensuel,
      livres_12m,
      heures_tv,
      confiance_science,
      sport_regulier
    ),
    statistic = list(
      revenu_mensuel ~ "{mean}",
      livres_12m ~ "{mean}",
      heures_tv ~ "{mean}",
      confiance_science ~ "{mean}",
      sport_regulier ~ "{p}%"
    ),
    type = list(
      confiance_science ~ "continuous",
      sport_regulier ~ "dichotomous"
    ),
    missing = "no",
    label = list(
      revenu_mensuel ~ "Revenu mensuel moyen (€)",
      livres_12m ~ "Livres lus en 12 mois",
      heures_tv ~ "Télévision (heures/jour)",
      confiance_science ~ "Confiance dans la science (1–5)",
      sport_regulier ~ "Sport au moins hebdomadaire"
    ),
    digits = list(
      revenu_mensuel ~ 0,
      livres_12m ~ 1,
      heures_tv ~ 1,
      confiance_science ~ 2,
      sport_regulier ~ 1
    )
  ) |>
  bold_labels()
Caractéristique Inférieur au bac
N = 1 6231
Bac
N = 6941
Bac+2
N = 5431
Supérieur long
N = 6681
Revenu mensuel moyen (€) 1 943 2 135 2 338 2 788
Livres lus en 12 mois 2,2 3,3 4,4 6,3
Télévision (heures/jour) 2,6 2,2 2,0 1,7
Confiance dans la science (1–5) 3,27 3,60 3,83 4,05
Sport au moins hebdomadaire 19,9% 34,3% 42,5% 50,3%
1 Moyenne; %

La force du tableau vient de sa cohérence substantive : chaque ligne renseigne une dimension susceptible de participer à la différenciation sociale des modes de vie. Ajouter dix variables sans rapport avec cette question affaiblirait le message.

NoteLecture sociologique

Un tableau comparatif n’est pas une collection neutre de chiffres. Le choix des lignes construit une représentation du phénomène. Ici, mettre côte à côte revenus, lecture, télévision, confiance dans la science et sport permet d’examiner si plusieurs dimensions se structurent parallèlement selon le diplôme. Ce rapprochement est descriptif : il ne démontre ni une cause commune ni un mécanisme unique.

13.7 Ajouter un IC lorsque la précision fait partie du message

Un tableau de publication n’a pas besoin d’un IC pour chaque ligne. En revanche, lorsqu’une estimation est centrale — par exemple une prévalence — l’intervalle apporte une information substantielle.

Afficher le code R
design |>
  tbl_svysummary(
    by = diplome_4,
    include = sport_regulier,
    statistic = sport_regulier ~ "{p}%",
    type = sport_regulier ~ "dichotomous",
    missing = "no",
    label = sport_regulier ~ "Sport au moins hebdomadaire"
  ) |>
  add_ci() |>
  bold_labels()
Caractéristique Inférieur au bac
N = 1 6231
95% IC Bac
N = 6941
95% IC Bac+2
N = 5431
95% IC Supérieur long
N = 6681
95% IC
Sport au moins hebdomadaire 20% 18%, 22% 34% 30%, 38% 43% 39%, 46% 50% 46%, 54%
1
Abréviation: IC = intervalle de confiance

La figure du chapitre 12 permet de voir la forme du gradient en un coup d’œil ; le tableau donne les valeurs exactes. Les deux supports sont complémentaires, pas concurrents.

13.8 add_p() : seulement si la question est réellement inférentielle

Ajouter une colonne de valeurs-p à toute Table 1 est devenu un automatisme fréquent. Il est pourtant souvent difficile à justifier :

  • si les groupes ne sont pas le résultat d’une expérimentation, une valeur-p ne « teste » pas l’équilibre causal ;
  • si le tableau contient vingt variables, la multiplicité devient centrale ;
  • si la question est descriptive, l’ordre de grandeur et l’incertitude suffisent souvent ;
  • si le test global est important, il doit être relié à une hypothèse explicitement formulée.

Le chapitre 16 montrera comment utiliser add_p() lorsque le tableau et le test répondent à la même question.

13.9 Labels, unités et précision numérique font partie de l’analyse

Un tableau destiné à être lu ne devrait pas afficher :

  • revenu_mensuel sans unité ;
  • diplome_4 sans libellé ;
  • 0.3186421 lorsque l’incertitude est de plusieurs points ;
  • Unknown sans expliquer ce qu’il signifie ;
  • des modalités dans l’ordre alphabétique si l’ordre substantiel est différent.
AvertissementLa précision numérique n’est pas la précision scientifique

Sept décimales indiquent seulement que l’ordinateur a conservé sept décimales. Elles ne signifient pas que l’estimation est connue avec cette précision.

13.10 Tableaux de régression : montrer le résultat, pas la mécanique

À partir du chapitre 17, gtsummary::tbl_regression() sera utilisé pour présenter les modèles. Le principe reste le même :

  • nommer la variable dépendante dans le texte ou le titre ;
  • afficher les catégories de référence ;
  • choisir coefficient, OR ou ratio selon l’échelle interprétable ;
  • inclure l’IC ;
  • éviter d’imprimer summary(model) puis un tableau contenant la même information ;
  • présenter séparément les comparaisons de modèles lorsqu’elles répondent à une question spécifique.

Un tableau de modèles n’est pas plus scientifique parce qu’il contient davantage de colonnes. Il est meilleur lorsque la progression des spécifications est justifiée et lisible.

13.11 Exporter vers Word : garder une source reproductible

Pour un travail collaboratif, on peut convertir un objet gtsummary en flextable puis l’exporter. Le principe est important : le tableau édité doit rester reproductible depuis R plutôt que devenir un objet Word impossible à reconstruire.

Afficher le code R
# Exemple d'export ponctuel
# tbl_final |>
#   as_flex_table() |>
#   flextable::save_as_docx(path = "outputs/tableau_final.docx")

13.12 Mini-exercice

Construisez deux tableaux de la même variable diplome_4 : l’un brut, l’autre pondéré. Ajoutez une note de bas de tableau qui rende impossible la confusion entre les deux.

Le tableau brut doit utiliser les effectifs ou parts des observations. Le tableau pondéré doit indiquer explicitement que les proportions sont estimées à partir du plan. Une bonne note précise également que les effectifs restent non pondérés.

13.13 Exercice de synthèse

13.13.1 Niveau A — Appliquer

Produisez une Table 1 avec âge, sexe, diplôme, revenu et sport. Utilisez des labels français et affichez les données manquantes lorsqu’elles existent.

13.13.2 Niveau B — Choisir

À partir du chapitre 11, construisez un tableau de gradient scolaire contenant au maximum cinq lignes. Justifiez chaque variable conservée et chaque variable écartée.

13.13.3 Niveau C — Analyser

Imaginez que votre tableau doive figurer dans un article. Rédigez : titre, note de méthode, note sur les poids, règle de gestion des manquants et deux phrases de résultat. Le lecteur doit pouvoir distinguer sans ambiguïté N observé, estimation pondérée et incertitude.

13.14 À retenir

  • Un tableau a une fonction : diagnostic, analyse ou publication.
  • tbl_summary() décrit les observations ; tbl_svysummary() calcule des statistiques à partir d’un objet survey.design (Sjoberg et al. 2021).
  • Les effectifs non pondérés et les estimations pondérées sont deux informations différentes et souvent complémentaires.
  • Les valeurs manquantes et les dénominateurs doivent être documentés lorsqu’ils influencent la lecture.
  • add_p() n’est pas une décoration automatique de Table 1.
  • Labels, unités, références et nombre de décimales font partie de la qualité scientifique du tableau.
  • Un bon tableau sélectionne l’information nécessaire à une question ; il n’essaie pas d’afficher tout ce que R peut calculer.

13.15 Pour aller plus loin

Nous avons maintenant des descriptifs, figures et tableaux propres. La partie suivante introduit l’incertitude : pourquoi une estimation varie d’un échantillon à l’autre et comment le plan d’enquête intervient dans cette variabilité.