Valider les données épidémiologiques
Dernière mise à jour le 2025-09-15 | Modifier cette page
Vue d'ensemble
Questions
- Comment convertir les données brutes en un objet de la classe
linelist
?
Objectifs
- Démontrez comment convertir les données portant sur les cas
épidémiques en objet de type
linelist
- Démontrer comment étiqueter et valider les données pour rendre l’analyse plus fiable
Pré-requis
Pour cet épisode vous devez :
- Télécharger le fichier cleaned_data.csv
- Et le sauvegarder dans le dossier
data/
.
Introduction
Après la lecture et le nettoyage des données, il est essentiel
d’ajouter une étape supplémentaire fondamentale pour garantir
l’intégrité et la fiabilité durant le processus d’analyse des données
épidémiologiques. Dans le cas contraire, vous risquez de rencontrer des
problèmes lors de l’analyse des données à cause de la création ou
suppression de certaines variables ou de la modification de leur type
(tel que <date>
ou <chr>
), etc.
Plus précisément, cette étape supplémentaire implique :
- La vérification de la présence de certaines colonnes et de leur type de données. Ce processus est communément appelé étiquetage ;
- La mise en œuvre de mesures pour s’assurer que ces colonnes étiquettées ne soient pas supprimées par inadvertance lors du traitement des données. On parle de validation des données.
Cet épisode est consacré à l’étiquettage et la validation des données
épidémiologiques à l’aide de la librairie {linelist}. Nous
aurons besoin de la librairie rio pour importer les
données, de linelist pour créer un objet de la classe
linelist. Nous utiliserons l’opérateur pipe (%>%
) pour
connecter certaines de leurs fonctions, y compris celles de la librairie
dplyr. Pour cette raison, nous allons donc charger la
librairie {tidyverse}.
R
# charger packages
library(tidyverse)
library(rio)
library(here)
library(linelist) # pour etiquetter et valider les donnees
L’opérateur double deux-points
(::
)
L’opérateur ::
de R permet d’accéder aux fonctions ou
aux objets d’un package spécifique sans attacher l’intégralité du
package (sans faire appel à la functionlibray()
). Il offre
plusieurs avantages, notamment :
- Indiquer explicitement le package d’origine d’une fonction, réduisant ainsi les ambiguïtés et les conflits potentiels lorsque plusieurs packages possèdent des fonctions portant le même nom.
- Permettre d’appeler une fonction depuis un package sans charger
l’intégralité du package avec
library()
.
Par exemple, la commande dplyr::filter(data, condition)
signifie que nous appelons la fonction filter()
depuis la
librairie dplyr.
Importez le jeu de données en suivant les directives énoncées dans l’épisode document Lecture des données épidémiologiques. Il s’agit d’importer les données dans l’environnement de travail et de visualiser sa structure et son contenu.
R
# lecture des données
# supposons que le chemin d'acces au fichier
# est: data/simulated_ebola_2.csv, alors:
cleaned_data <- rio::import(
here::here("data", "cleaned_data.csv")
) %>%
dplyr::as_tibble()
# voir un aperçu des 10 premieres ligne du tableau de donnees
cleaned_data
SORTIE
# A tibble: 15,000 × 10
v_1 case_id age gender status date_onset date_sample row_id
<int> <int> <dbl> <chr> <chr> <IDate> <IDate> <int>
1 1 14905 90 male confirmed 2015-03-15 2015-04-06 1
2 2 13043 25 female <NA> 2013-09-11 2014-01-03 2
3 3 14364 54 female <NA> 2014-02-09 2015-03-03 3
4 4 14675 90 <NA> <NA> 2014-10-19 2014-12-31 4
5 5 12648 74 female <NA> 2014-06-08 2016-10-10 5
6 6 14274 76 female <NA> 2015-04-05 2016-01-23 7
7 7 14132 16 male confirmed NA 2015-10-05 8
8 8 14715 44 female confirmed NA 2016-04-24 9
9 9 13435 26 male <NA> 2014-07-09 2014-09-20 10
10 10 14816 30 female <NA> 2015-06-29 2015-02-06 11
# ℹ 14,990 more rows
# ℹ 2 more variables: years_since_collection <int>, remainder_months <int>
Discussion
Avez-vous déjà été confronté à une modification inattendue de certaines observations et/ou colonnes de vos données d’entrée lors d’une analyse épidémiologique ? Comment protégez-vous votre analyse de ce désagrément ?
Un changement inattendu
Vous êtes dans une situation d’urgence. Vous devez produire des rapports de situation quotidiennes. Vous avez automatisé votre analyse pour lire les données directement à partir du serveur en ligne :grin :. Cependant, les personnes chargées de la collecte et de l’administration des données devaient supprimer/renommer/reformater une variable qui s’est afférée utile 😞 !
Comment pouvez-vous détecter si les données saisies sont toujours valides pour reproduire l’analyse en utilisant le même code que la veille ?
Création d’un objet de type linelist et étiquetage des colonnes
Après avoir importé et nettoyé les données, nous pouvons les
convertir en un objet de la classe linelist
à l’aide de la
fonction make_linelist()
de la librairie
linelist comme dans l’exemple suivant ci-dessous.
R
# creer un objet de type linelist a partir des donnees nettoyees
linelist_data <- linelist::make_linelist(
x = cleaned_data, # les donnees d'entree
id = "case_id", # colonne avec les identifiants uniques des individus
date_onset = "date_onset", # colonne avec la date d'apparition des symptomes
gender = "gender" # colonne ayant le genre des individus
)
# voir un aperçu de l'objet cree
linelist_data
SORTIE
// linelist object
# A tibble: 15,000 × 10
v_1 case_id age gender status date_onset date_sample row_id
<int> <int> <dbl> <chr> <chr> <IDate> <IDate> <int>
1 1 14905 90 male confirmed 2015-03-15 2015-04-06 1
2 2 13043 25 female <NA> 2013-09-11 2014-01-03 2
3 3 14364 54 female <NA> 2014-02-09 2015-03-03 3
4 4 14675 90 <NA> <NA> 2014-10-19 2014-12-31 4
5 5 12648 74 female <NA> 2014-06-08 2016-10-10 5
6 6 14274 76 female <NA> 2015-04-05 2016-01-23 7
7 7 14132 16 male confirmed NA 2015-10-05 8
8 8 14715 44 female confirmed NA 2016-04-24 9
9 9 13435 26 male <NA> 2014-07-09 2014-09-20 10
10 10 14816 30 female <NA> 2015-06-29 2015-02-06 11
# ℹ 14,990 more rows
# ℹ 2 more variables: years_since_collection <int>, remainder_months <int>
// tags: id:case_id, date_onset:date_onset, gender:gender
La librairie linelist fournit des étiquettes aux
variables épidémiologiques courantes et leurs associe un ensemble de
types de données appropriés. Vous pouvez consulter la liste des
étiquettes disponibles à partir du nom de la variable et les types de
données acceptables pour chacune d’entre elles en utilisant la fonction
linelist::tags_types()
.
Défi
Etiquettons d’autres variables. Dans certains jeu de données, il est possible de trouver des noms de variables qui sont différents des noms des étiquettes disponibles. Dans ces cas là, nous pouvons les associer en fonction de la façon dont les variables ont été définies durant la collecte des données.
Maintenant:
- Explorer les noms de étiquettes disponibles dans {linelist}.
- Trouver quelles autres variables de ce jeu de données peuvent être associées à l’une des étiquettes disponibles.
-
Étiquetter ces variables comme on l’a montré
ci-dessus en utilisant la fonction
linelist::make_linelist()
.
Vous pouvez accéder à la liste des noms des étiquettes disponibles dans la librairie {linelist} en utilisant :
R
# obtenir la liste des noms et types des etiquettes
linelist::tags_types()
# obtenir la liste des noms des etiquettes uniquement
linelist::tags_names()
R
linelist::make_linelist(
x = cleaned_data,
id = "case_id",
date_onset = "date_onset",
gender = "gender",
age = "age", # meme nom que celui utilise dans la liste des etiquettes
date_reporting = "date_sample" # noms differents mais lies
)
Comment apparaissent ces étiquettes supplémentaires dans le nouveau objet ?
Validation
Pour s’assurer que toutes les variables étiquettées sont aux normes
et que leurs types de données sont correctes, utilisez la fonction
linelist::validate_linelist()
comme le montre l’exemple
ci-dessous :
R
linelist::validate_linelist(linelist_data)
SORTIE
'linelist_data' is a valid linelist object
Défi
Imaginons le scénario suivant lors d’une épidémie en cours. Vous remarquez à un moment donné que la source de données sur laquelle vous vous appuyiez comporte un ensemble de nouvelles entrées (c’est-à-dire des lignes ou des observations) et que le type de données d’une variable a changé.
Prenons l’exemple où le type de la variable age
est
passé de double (<dbl>
) à caractère
(<chr>
).
Pour simuler cette situation :
- Modifiez le type de données de la variable,
- Étiquetez la variable dans un object linelist, puis
- Validez la variable.
Décrivez comment linelist::validate_linelist()
réagit
lorsque le type de données d’une variable a été modifié.
Nous pouvons utiliser dplyr::mutate()
pour modifier le
type de la variable avant de l’étiqueter pour la validation.
R
cleaned_data %>%
# modifier le type de donnees d'une variable
dplyr::mutate(age = as.character(age)) %>%
# etiqueter variable
linelist::... %>%
# valider l'objet linelist
linelist::...
Veuillez exécuter le code ligne par ligne, en vous concentrant uniquement sur les parties situées avant l’opérateur pipe (
%>%
). Après chaque étape, observez la sortie avant de passer à la ligne suivante.
Si le résultat age
passe de double
(<dbl>
) en caractère (<chr>
), nous
obtenons ce qui suit :
R
cleaned_data %>%
# convertir la variable 'age' en chaine de caracteres
dplyr::mutate(age = as.character(age)) %>%
# etiqueter la variable age
linelist::make_linelist(age = "age") %>%
# valider l'objet linelist
linelist::validate_linelist()
ERREUR
Error: Some tags have the wrong class:
- age: Must inherit from class 'numeric'/'integer', but has class 'character'
Pourquoi recevons-nous un message d'Erreur
?
Devrions-nous avoir un message d’alerte à la place ? Expliquez pourquoi. Explorez d’autres situations pour comprendre ce comportement en convertissant:
-
date_onset
de<date>
en caractère (<chr>
), -
gender
de caractère (<chr>
) en nombre entier (<int>
).
Ensuite, étiquetez-les dans dans l’objet linelist pour validation.
Est-ce que le message d'Erreur
nous propose-t-il une
solution ?
R
# deuxieme changement
# executer ce code ligne par ligne pour voir les changements
cleaned_data %>%
# modifier le type de la variable 'date_onset'
dplyr::mutate(date_onset = as.character(date_onset)) %>%
# tiqueter le variable 'date_onset'
linelist::make_linelist(
date_onset = "date_onset"
) %>%
# valider l'objet linelist
linelist::validate_linelist()
R
# troisieme changement
# executer ce code ligne par ligne pour voir les changements
cleaned_data %>%
# modifier le type de la variable 'gender'
dplyr::mutate(gender = as.factor(gender)) %>%
dplyr::mutate(gender = as.integer(gender)) %>%
# etiqueter la variable 'gender'
linelist::make_linelist(
gender = "gender"
) %>%
# valider l'objet linelist
linelist::validate_linelist()
Nous obtenons des messages d'Erreur
car le type par
défaut de ces variables dans linelist::tags_types()
est
différent de celui dont on les a associé.
Le message d'Erreur
nous informe que pour
valider notre objet linelist, nous devons changer le
type de variable d’entrée de sorte qu’il corresponde au type d’étiquette
attendu. Dans un script d’analyse de données, nous pouvons le faire en
ajoutant une étape de nettoyage dans le pipeline.
Défi
En dehors de l’étiquetage et de la validation de l’objet linelist, de quelle autre étape avons-nous besoin lors de la construction de l’objet ?
Voici un scénario où nous allons essayer d’étiqueter une variable qui n’existe pas dans notre jeu de données.
R
cleaned_data %>%
# supprimer la variable 'age'
select(-age) %>%
# etiqueter la variable 'age' qui n'existe plus
linelist::make_linelist(age = "age")
ERREUR
Error in base::tryCatch(base::withCallingHandlers({: 1 assertions failed:
* Variable 'tag': Must be element of set
* {'v_1','case_id','gender','status','date_onset','date_sample','row_id','years_since_collection','remainder_months'},
* but is 'age'.
On a donc besoin de mettre en place un mécanisme pour protéger les données de toutes actions inopportunes.
Protéger les données
La protection des données est implicitement intégrée dans les objets de la classe linelist. Si vous essayez de supprimer l’une des variables étiquetées, vous recevrez un message d’erreur ou d’avertissement, comme le montre l’exemple ci-dessous.
R
new_df <- linelist_data %>%
dplyr::select(case_id, gender)
AVERTISSEMENT
Warning: The following tags have lost their variable:
date_onset:date_onset
Ce message d’avertissement qui s’affiche est l’option par défaut
lorsque nous perdons des étiquetes dans un objet de la classe linelist.
Cependant, il peut être remplacé par un message d'Erreur
en
utilisant la fonction linelist::lost_tags_action()
.
Défi
Testons les implications de la variation de la configuration de
protection d’un objet linelist de
Avertissement
à Erreur
.
- Tout d’abord, exécutez ce code pour compter la fréquence des catégorie au sein d’une variable catégorielle :
R
linelist_data %>%
dplyr::select(case_id, gender) %>%
dplyr::count(gender)
- Spéficier qu’on souhaite obtenir un message d’Erreur au lieu d’un Avertissement à la suite de la perte d’une variable étiquetée de l’objet linelist :
R
# retourner une erreur
linelist::lost_tags_action(action = "error")
- Maintenant, réexécutez le bloc de code ci-dessus avec
dplyr::count()
. - Quelle est la différence entre le message
d'Avertissement
et le messaged'Erreur
? - Quelles pourraient être les implications de ce changement pour votre pipeline d’analyse quotidienne de données lors d’une réponse à une épidémie ?
Décider entre Avertir et continuer l'exécution du code
ou Arréter l'exécution du code avec un message d'erreur
dépendra du niveau d’importance et de flexibilité dont vous avez besoin
lorsque vous perdez des étiquettes. L’un vous alertera d’un changement
mais continuera à exécuter le code en aval. L’autre arrêtera votre
pipeline d’analyse et le reste ne sera pas exécuté.
Un script de lecture, nettoyage et validation de données peut nécessiter un pipeline plus stable ou fixe. Une analyse exploratoire des données peut nécessiter une approche plus souple. Ces deux processus peuvent être isolés dans des scripts ou des dossiers différents afin d’adapter le mécanisme de protection à vos besoins.
Avant de continuer, rétablissez la configuration à l’option par
défaut de Avertissement
:
R
# retablir l'option par defaut: "warning"
linelist::lost_tags_action()
SORTIE
Lost tags will now issue a warning.
A objet linelist
ressemble à un data frame mais offre
des caractéristiques et fonctionnalités plus riches. Les librairies qui
prennent en compte les objets linelist peuvent exploiter ces
fonctionnalités. Par exemple, vous pouvez extraire un data frame
contenant uniquement les colonnes étiquetées à l’aide de la fonction
linelist::tags_df()
comme indiqué ci-dessous :
R
# extraire uniquement les colonnes étiquetées
linelist::tags_df(linelist_data)
SORTIE
# A tibble: 15,000 × 3
id date_onset gender
<int> <IDate> <chr>
1 14905 2015-03-15 male
2 13043 2013-09-11 female
3 14364 2014-02-09 female
4 14675 2014-10-19 <NA>
5 12648 2014-06-08 female
6 14274 2015-04-05 female
7 14132 NA male
8 14715 NA female
9 13435 2014-07-09 male
10 14816 2015-06-29 female
# ℹ 14,990 more rows
Avec la librairie cleanepi, vous pouvez également
choisir d’appliquer certaines opérations de nettoyage de données
uniquement sur les les colonnes étiquetées. Il suffira de donner la
valeur "linelist_tags"
à l’argument
target_columns
de la finction correspondante.
R
# identifier les doublons uniquement à travers les colonnes etiquetees
linelist_data %>%
cleanepi::find_duplicates(target_columns = "linelist_tags")
SORTIE
! Found 177 duplicated rows in the dataset.
ℹ Use `attr(dat, "report")[["duplicated_rows"]]` to access them, where "dat" is
the object used to store the output from this operation.
SORTIE
// linelist object
# A tibble: 15,000 × 10
v_1 case_id age gender status date_onset date_sample row_id
<int> <int> <dbl> <chr> <chr> <IDate> <IDate> <int>
1 1 14905 90 male confirmed 2015-03-15 2015-04-06 1
2 2 13043 25 female <NA> 2013-09-11 2014-01-03 2
3 3 14364 54 female <NA> 2014-02-09 2015-03-03 3
4 4 14675 90 <NA> <NA> 2014-10-19 2014-12-31 4
5 5 12648 74 female <NA> 2014-06-08 2016-10-10 5
6 6 14274 76 female <NA> 2015-04-05 2016-01-23 7
7 7 14132 16 male confirmed NA 2015-10-05 8
8 8 14715 44 female confirmed NA 2016-04-24 9
9 9 13435 26 male <NA> 2014-07-09 2014-09-20 10
10 10 14816 30 female <NA> 2015-06-29 2015-02-06 11
# ℹ 14,990 more rows
# ℹ 2 more variables: years_since_collection <int>, remainder_months <int>
// tags: id:case_id, date_onset:date_onset, gender:gender
Quand dois-je utiliser
{linelist}
?
L’analyse des données au cours d’une réponse à une épidémie ou d’une surveillance de masse exige un ensemble de différentes façons de “protéger les données” par rapport aux situations de recherche habituelles. Par exemple, vos données changeront ou seront mises à jour au fil du temps avec de nouvelles entrées, nouvelles variables, des variables seront renommées, etc.
La librairie linelist est plus appropriée pour ce type de surveillance continue, mais aussi aux analyses de données générée sur une longue période. Consultez la section de la vignette “Get started” à propos de When I should consider using {linelist}? pour plus d’informations.
Points clés
- Utiliser la librairie linelist pour étiqueter, valider et protéger les données épidémiologiques pour l’analyse en aval.