Tableaux récapitulatifs

Core
Tableaux de resumé
Créer des tableaux récapitulatifs
Date de publication

21 février 2025

Objectifs

  • Créer des tableaux de contingence avec count()
  • Calculer des statistiques récapitulatives par groupe à l’aide de summarize()
  • Réviser comment sélectionner les lignes en utilisant filter() et créer/modifier des variables avec mutate()
  • Créer des variables catégorielles ordonnées

Configuration

Dépendances. Cette session suppose que vous savez utiliser RStudio, que vous êtes capable d’importer des données et que vous connaissez les verbes de base de manipulation des données que nous avons vus dans les sessions de base jusqu’à présent. Si vous avez besoin d’un rappel sur l’un de ces sujets, nous vous encourageons à revoir les sessions de base du parcours d’apprentissage.

Cette session utilisera la version nettoyée de l’ensemble de données Moissala sur la rougeole. Téléchargez les données et stockez-les dans data/clean dans votre projet d’entraînement :


Ouvrez votre projet RStudio et créez un nouveau script dans le sous-dossier R appelé tables.R avec les métadonnées appropriées et une section “Packages” qui importe : {rio}, {here} et {tidyverse}. Ajoutez une section “Import Data” qui charge la version nettoyée de la linelist de la rougeole dans R.

Introduction : agrégation des données

Récapitulons. Vous venez d’effectuer l’une des tâches les [plus importantes]{.hovertip bs-toggle=‘tooltip’ bs-title=’Certains considèrent que cela représente 80 % du travail !} d’un épidémiologiste : le nettoyage des données. Maintenant que vous disposez de données propres et normalisées, vous pouvez vous mettre au travail et commencer à les analyser. Les analyses commencent généralement par des tableaux et des résumés qui décrivent nos données :

  • Tableaux de fréquence univariés pour compter les occurrences de différentes valeurs
  • Statistiques sommaires des variables numériques (moyenne, médiane, écart-type)
  • Tableaux croisés pour examiner les relations entre les variables catégorielles
  • Résumés par groupe pour comparer les statistiques entre différents sous-ensembles de données

Compter plusieurs colonnes (tableaux de contingence)

Au cours de la session d’exploration des données, vous avez appris à créer un tableau de fréquence pour une variable catégorielle unique à l’aide de la fonction count(). C’est bien, mais nous voulons souvent compter le nombre d’observations en fonction de deux variables (ou plus !).

Ces tableaux sont appelés tableaux de contingence. Par exemple, connaître le nombre de patients par sous-préfecture est très utile, mais nous pourrions vouloir stratifier à la fois par sous-préfecture et par groupe d’âge pour voir si certaines zones ont des patients anormalement âgés. Ce type de stratification est un moyen utile d’essayer de trouver des zones qui pourraient être de bons candidats pour des campagnes de rattrapage. C’est facile, il suffit de passer plusieurs noms de colonnes à count() :

df_linelist |>
  count(sous_prefecture, age_groupe)

Créez un nouveau tableau récapitulatif en comptant le nombre de patients stratifiés par sous_prefecture et hospitalisation. Que se passe-t-il si vous modifiez l’ordre des arguments donnés à count() ?

Maintenant, en utilisant count(), réponds aux questions suivantes :

  • Combien de patients étaient des femmes ? Quelle est la proportion ?
  • Quelles sont toutes les valeurs possibles de la variable statut_sortie ?
  • Combien de patients âgés de 1 à 4 ans se sont rétablis ?

Filtrer les valeurs NA

En examinant les catégories du statut_sortie, vous devriez avoir remarqué que certaines patientes ont des valeurs manquantes (NA):

df_linelist |>
  count(statut_sortie) |>
  mutate(prop = n / sum(n))

Observez le résultat du code ci-dessus. Comment pouvez-vous également calculer la proportion de patients décédés ? Êtes-vous satisfait de ce calcul ?

La proportion de cas décédés est également appelée taux de létalité. Pour calculer précisément le CFR, nous devons nous assurer que le dénominateur ne comprend que les patients dont nous sommes sûrs du résultat (c’est-à-dire que nous devons supprimer tous les cas avec “NA” ou “contre avis médical”).

Rappelons que nous pouvons le faire en utilisant filter(). Pour garder les valeurs manquantes (NA) dans une variable, nous pouvons utiliser la petite fonction is.na(statut_sortie). L’ajout d’un ! devant fera l’inverse : supprimer les valeurs manquantes de statut_sortie :

df_linelist |>
  filter(statut_sortie != "sortie contre avis medical", 
         !is.na(statut_sortie)) |>
  count(statut_sortie)

Quelle autre instruction conditionnelle pourriez-vous utiliser dans filter() pour obtenir les mêmes résultats ?

Maintenant que nous avons supprimé les patients dont l’issue est inconnue, nous pouvons ajouter ceci avant de créer notre tableau de fréquence pour obtenir le CFR correct.

À l’aide de votre filtre, mettez à jour votre code pour résumer le nombre observé de patients qui ont survécu et sont décédés ainsi que le taux de létalité (proportion de décès). Stockez ce nouveau dataframe dans un objet, cfr_df.

Astuce

Bonus. Une fonction de “raccourci” utile est drop_na() du package {tidyr} qui équivaut à filter(!is.na()).

df_linelist |>
  drop_na(statut_sortie) |>
  count(statut_sortie)

drop_na() est particulièrement utile car vous pouvez lui donner plusieurs noms de colonnes pour filtrer. Mais attention, cela supprimera toutes les lignes où une ou plusieurs de ces colonnes ont une valeur manquante.

Tableau récapitulatif : statistiques par sous-préfecture

Maintenant que nous avons produit quelques tableaux de fréquence et de contingence simples, nous pouvons augmenter la complexité. Une tâche courante en épidémiologie consiste à examiner les statistiques résumées dans des sous-ensembles de données.

Par exemple, on peut nous demander de produire des statistiques sur les patients au niveau des sous-préfectures, c’est-à-dire que pour chaque sous-préfecture dans les données, nous devons répondre aux questions suivantes :

  • Combien de patients ont été consultés ?
  • Quel est leur âge moyen ?
  • Quelle a été la date d’admission la plus ancienne ?
  • Combien de patients ont été hospitalisés ?
  • Parmi les enfants de moins de 6 mois, combien sont décédés ?

C’est exactement pour cela que la fonction summarize() a été créée ! Elle nous permet de calculer des statistiques résumées sur un ensemble de données, et la syntaxe est similaire à celle de mutate() :

# NE PAS EXÉCUTER (PSEUDO-CODE)
df |>
  mutate(new_col = function_to_create(existing_col))

df |>
  summarize(.by = grouping_variable,
            new_col = summary_function(existing_col))

Considérons le code suivant, où nous résumons les données pour calculer l’âge moyen de tous les patients.

df_linelist |>
  summarize(moy_age = mean(age))
# A tibble: 1 × 1
  moy_age
    <dbl>
1    6.82

Notez que ce code donne une seule valeur pour l’âge moyen. Aucune variable de regroupement n’a été fournie, donc summarize() a renvoyé une statistique récapitulative pour l’ensemble du jeu de données. Pour calculer l’âge moyen par strate spécifique, nous devons spécifier une variable de regroupement en utilisant l’argument .by :

df_linelist |>
  summarize(.by = sexe, # Faire le résumé (ici, la moyenne) par sexe
            moy_age = mean(age))
# A tibble: 2 × 2
  sexe  moy_age
  <chr>   <dbl>
1 f        6.77
2 m        6.87

Jetez un œil aux résultats ci-dessus. Comment les interprétez-vous ?

Maintenant que nous pouvons utiliser summarize(), nous pouvons l’utiliser pour calculer des statistiques récapitulatives appropriées par sous-préfecture. Commençons par appeler un summarize() vide et regrouper les données sur sous_prefecture.

Exécutez le code suivant :

df_linelist |>
  summarize(.by = sous_prefecture)

Que se passe-t-il lorsque vous exécutez ces lignes ?

Comptages

Nous voulons d’abord examiner le nombre de cas dans chaque sous_prefecture. Cela peut être fait en utilisant la fonction d’aide n() :

df_linelist |>
  summarize(.by = sous_prefecture,
            n_patients = n()  # pour compter
)

Ok, maintenant construisons un tableau récapitulatif pour chaque sous-préfecture. Commençons par reproduire les lignes ci-dessus.

Récapitulatifs des variables continus

Nous pouvons ensuite utiliser les fonctions mean(), median(), min(), max() (et autres) pour produire des récapitulatifs pour les variables continues. Par exemple, l’âge moyen :

df_linelist |>
  summarize(.by = sous_prefecture,
            n_patients = n(),
            mean_age = mean(age))

Ajoutez la date d’admission minimale à votre tableau pour chacune des sous_prefecture ? Êtes-vous satisfait des résultats ?

Astuce

N’oubliez pas qu’avec les fonctions arithmétiques telles que mean(), median(), min(), max(), vous devez indiquer explicitement à R de supprimer NA.

Comptage avec une condition

Nous pouvons également être intéressés par le nombre de patients (lignes) qui répondent à une condition : le nombre de patients de sexe féminin. Le comptage par condition logique peut être effectué avec la syntaxe suivante :

# NE PAS EXÉCUTER (PSEUDO-CODE)
summarize(sum_category = sum(LOGIC_TEST, na.rm = TRUE))

Cette somme nous permet de compter toutes les lignes où notre condition a été remplie (retourne TRUE). Par exemple :

Cette somme nous permet de compter toutes les lignes où notre condition a été remplie (retourne TRUE). Par exemple :

df_linelist |>
  summarize(.by = sous_prefecture,
            n_female = sum(sexe == "f", na.rm = TRUE))

Ajoutez une variable à votre tableau qui compte le nombre de patients qui ont été hospitalisés. (c’est-à-dire : les lignes qui ont “oui” dans la variable “hospitalisation”)

Autres statistiques

Parfois, nous voulons produire une statistique plus compliquée, par exemple l’âge moyen de tous les patients hospitalisés. Ici, la syntaxe est un peu différente :

# NE PAS EXÉCUTER (PSEUDO-CODE)
df |>
  summarize(mean_category = mean(col_to_use[LOGIC_TEST], na.rm = TRUE))

Ici, nous avons : - Indiqué quelle statistique de synthèse nous voulons utiliser (mean()) - Indiqué sur quelle colonne nous voulons calculer cette statistique (col_to_use) - Création d’une condition indiquant les observations de cette colonne à utiliser dans le calcul ([LOGIC_TEST])

Pour donner un exemple concret, si nous voulions calculer la moyenne de la variable age mais uniquement pour les patients hospitalisés (c’est-à-dire dans les lignes où hospitalisation == "oui") nous écririons :

df_linelist |>
  summarize(.by = sous_prefecture,
            n_patients = n(),
            moy_age_hosp = mean(age[hospitalisation == "oui"], na.rm = TRUE))

L’utilisation d’un test logique dans l’exemple ci-dessus est appelée indexation logique, où une condition est essentiellement utilisée pour filtrer les observations que vous souhaitez prendre en compte lors d’un calcul. L’indexation logique est très puissante, mais elle peut aussi demander un certain temps d’adaptation, alors ne vous inquiétez pas trop si ce n’est pas parfaitement clair à ce stade.

Pouvez-vous utiliser cette syntaxe pour calculer l’âge moyen des patientes dans votre tableau ?

C’est très bien ! Nous commençons à obtenir un tableau récapitulatif groupé assez exhaustif avec beaucoup d’informations utiles par “sous-préfecture” ! Un défi supplémentaire pour vous :

DÉFI : Pourriez-vous ajouter une variable à votre tableau qui compte le nombre de patients décédés parmi ceux qui ont < 6 mois.


Note. Vous voulez compter les lignes (donc utiliser sum()) qui remplissent une condition spécifique pour le résultat (statut_sortie == "deces"), mais uniquement lorsque age_group == "< 6 months"

Utiliser la sortie

Enfin, n’oubliez pas que summarize() renvoie un dataframe que nous pouvons ensuite manipuler davantage (par exemple : avec filter() et mutate()).

Ajoutez un mutate() après avoir produit votre tableau récapitulatif pour calculer :

  • La proportion de patients hospitalisés par sous-préfecture
  • La proportion de patientes par sous-préfecture

L’en-tête de votre tableau final devrait ressembler à ceci :

# A tibble: 6 × 11
  sous_prefecture n_patients moy_age min_admission n_femme n_hosp moy_age_hosp
  <chr>                <int>   <dbl> <date>          <int>  <int>        <dbl>
1 Moissala              1808    6.84 2022-08-14        923    612         5.49
2 Bouna                 1376    6.56 2023-01-11        669    412         5.67
3 Bedjondo               534    7.07 2023-06-09        251    184         5.21
4 Bekourou               496    6.84 2023-06-17        251    164         6.04
5 Bedaya                 435    7.10 2023-07-04        209    147         6.16
6 Koumra                 253    7.11 2023-08-14        138     84         6.26
# ℹ 4 more variables: moy_age_femme <dbl>, n_deces_moins_6m <int>,
#   prop_female <dbl>, prop_hosp <dbl>

C’est fait !

Vous devriez être fiers de vous, la création de tableaux récapitulatifs est une compétence importante pour un épidémiologiste, et le faire en R est très efficace ! N’oubliez pas de sauvegarder votre code !

Pour aller plus loin

Exercices supplémentaires

  1. Créez un tableau récapitulatif qui calcule les statistiques suivantes par groupes d’âge :
  • Le nombre de patients
  • La proportion d’hommes
  • Le nombre de décès
  • Le CFR
  • Le nombre de décès parmi les patients atteints de pneumonie
  1. Faites un tableau qui montre la proportion de patients par âge ayant reçu un vaccin contre la rougeole (par rappel oral ou par carte) et ceux qui ont reçu 1 ou 2 doses.

  2. Faites un tableau comparant la proportion de patients hospitalisés et non hospitalisés présentant un TDR positif pour le paludisme, de la fièvre, une éruption cutanée, une toux, des yeux rouges, une pneumonie, une encéphalite et un MUAC « rouge » ou « jaune » (moins de 125 mm).

  3. Calculer le nombre moyen de jours entre l’apparition des premiers symptômes et la consultation par sous-préfecture.

  4. Calculer le temps moyen passé à l’hôpital (i.e. jours entre l’admission et le résultat) par résultat (i.e. chez ceux qui ont guéri et ceux qui sont décédés).

Ressources supplémentaires