Vous venez tout juste de commencer un stage comme ingénieur·e de données junior dans une grande compagnie d’assurance. Vous travaillez avec Alex, un·e analyste d’affaires expérimenté·e, qui vous a confié une mission importante.
Alex vous a fourni une base de données extraite d’un ancien système d’archives. Cette base contient des informations clés sur les clients, les polices d’assurance et les réclamations. Malheureusement, la base est truffée d’erreurs potentielles : valeurs manquantes, incohérences, erreurs de format, fautes de frappe, valeurs aberrantes et doublons possibles à vérifier.
Votre rôle sera d’assurer la qualité des données pour permettre à Alex de faire une analyse fiable. Certaines erreurs seront corrigées; d’autres seront seulement signalées si l’information disponible ne permet pas de choisir une correction défendable.
Carte de visite
Votre rôleIngénieur·e de données junior
InterlocuteurAlex, responsable de l’équipe analytique
Organisation et contexteCompagnie d’assurance fictive
MissionNettoyer une archive client et documenter les décisions de correction
Donnéesdataset_pratique.csv
Livrabledonnees_propres.csv, journal_nettoyage.Rdata et rapport Quarto
Objectifs de l’aventure
Importer une base de données brute (dataset_pratique.csv).
Identifier différents types d’erreurs courantes.
Nettoyer et transformer les données avec dplyr, forcats et stringr.
Documenter de façon claire toutes les modifications apportées à la base.
Comment réussir cette aventure ?
À la fin de cette aventure, vous devrez :
Fournir une base de données propre (donnees_propres.csv).
Maintenir une liste R structurée appelée journal_nettoyage dans votre script.
Sauvegarder cette liste dans un fichier journal_nettoyage.Rdata.
Pensez à documenter chaque étape de votre nettoyage. Votre rigueur est votre meilleure alliée !
Typologie des erreurs et structure de la liste
Voici un tableau de référence pour les types d’erreurs que vous pouvez rencontrer :
Code
Type d’erreur
Description
Exemple
VM
Valeurs manquantes
Champs essentiels non remplis
Lignes sans valeur pour age ou revenu_annuel
DF
Doublons
Lignes identiques ou très similaires
Deux lignes avec le même id_client
IF
Incohérences de format
Données du même type mais formats différents
date_naissance en formats mixtes (1980-01-01, 01/01/1980)
VA
Valeurs aberrantes
Valeurs manifestement extrêmes ou irréalistes
revenu_annuel = 99,999,999 $
FT
Fautes de frappe
Erreurs typographiques affectant la cohérence
Province inscrite comme “Quebéc”, “quebec”, “Québec”
RC
Recodage ou regroupement
Catégories similaires à fusionner
“sans emploi”, “inactif”, “au chômage”
TY
Types mal définis
Mauvais type de variable pour les données
revenu_annuel enregistré comme texte
LG
Erreurs logiques
Relations temporelles ou conditionnelles incorrectes
Client né en 2022 mais contrat signé en 2020
CI
Incohérences inter-variables
Données incohérentes entre deux colonnes
province = "Québec" mais code_postal commence par “H”
Cette typologie permet de structurer rigoureusement la détection et la documentation des erreurs dans le journal de nettoyage R (liste journal_nettoyage).
Dans votre script, vous allez construire la liste journal_nettoyage structurée par catégorie :
journal_nettoyage<-list( VM =list(list( id =c(12, 27), variables ="age", probleme ="Valeurs manquantes", action ="Remplacé par la médiane", justification ="Pour garder la cohérence")), DF =list(list( id =c(45, 46), variables ="id_client", probleme ="Doublons complets", action ="Suppression", justification ="Inutiles pour l’analyse")), IF =list(), VA =list(), FT =list(), RC =list(), TY =list(), LG =list(), CI =list(), RU =list(), TR =list(), EC =list())journal_nettoyage
Chaque catégorie (VM, DF, etc.) contient une liste de corrections, où chaque correction est un list() avec :
id : ligne(s) ou position(s) affectée(s)
variables : les variables concernées
probleme : nature du problème
action : action effectuée
justification : pourquoi cette action a été choisie
Cette structure vous aidera à rendre compte de vos modifications de façon propre et professionnelle.
GitHub et rendu
Comme pour les aventures précédentes :
Clonez le dépôt GitHub du module 4 depuis l’organisation du cours. Vous pouvez utiliser la cheat sheet du cours si vous avez un trou de mémoire.
Travaillez dans RStudio et faites des commits régulièrement pour documenter votre avancement.
Votre dépôt doit contenir :
le script .qmd de votre aventure, c’est-à-dire un document où vous faites vos tests et construisez votre liste journal_nettoyage ;
la liste journal_nettoyage dans un objet .Rdata ;
la base de données nettoyée au format .csv.
Bonne chance, et que vos données soient propres !
Importation des données
Avant de nettoyer une base de données, il faut savoir l’importer correctement. Pour cette mission, Alex vous a transmis le fichier dataset_pratique.csv. Ce fichier est séparé par des points-virgules. Il vous recommande de :
charger les données dans R avec la fonction read_delim() du package readr,
examiner les premières lignes pour repérer les incohérences évidentes,
et convertir immédiatement les noms de colonnes en minuscules avec janitor::clean_names() pour faciliter les manipulations à venir.
Si vous utilisez read_csv() ici, tout le fichier sera lu comme une seule colonne. C’est un bon réflexe de vérifier ncol(base) juste après l’importation.
Alex : « Cette base est un vrai casse-tête ! J’ai besoin que tu la rendes exploitable rapidement. Tu devrais commencer par repérer ce qui cloche dans les noms, les formats ou les valeurs. »
Exploration initiale des problèmes potentiels
Format des variables
Maintenant que vous avez importé la base, il est temps de faire une première exploration pour identifier les erreurs potentielles. Voici quelques étapes clés à suivre :
# Dimensions de la basenrow(base)ncol(base)# Variables disponiblesnames(base)# type des variablesglimpse(base)
Alex : « Tu verras, certains types des variables ne font aucun sens… Garde une trace de tout ce que tu trouves bizarre pour qu’on décide ensemble quoi en faire. »
L’une des fonctions les plus utiles ici est glimpse() (du package dplyr). Elle affiche un aperçu des premières valeurs de chaque variable ainsi que leur type : par exemple chr pour une chaîne de caractères (character), dbl pour un nombre décimal (double), int pour un entier, ou encore lgl pour un booléen.
Voici un rappel des principaux types de données en R :
character (chr) : texte
numeric / double (dbl) : nombres réels
integer (int) : nombres entiers
logical (lgl) : booléens (TRUE, FALSE)
factor : variable catégorielle à niveaux définis
Date : date au format standard R
Pour transformer une variable, vous pouvez utiliser les fonctions suivantes :
Pensez à toujours vérifier le résultat de la transformation avec glimpse() ou summary().
Alex : « Quand on regarde les types de variables avec glimpse(), il faut garder en tête qu’il y a des standards en science des données. En général, les variables contenant du texte devraient être de type character ou factor si elles prennent un nombre limité de valeurs (par exemple, une colonne sexe ou province). Les variables contenant des nombres devraient normalement être de type dbl (pour les décimaux) ou int (pour les entiers), selon le cas.
Un piège courant, c’est les identifiants ! Même s’ils ont l’air d’être des nombres, comme une colonne ID_client ou numero_contrat, ce ne sont pas des quantités sur lesquelles on va faire des calculs. Ce sont des étiquettes uniques. On devrait donc les convertir en character. Ça évite qu’un identifiant comme 0012 soit transformé en 12 par erreur, ou que R pense qu’on veut faire une moyenne avec ça…
Bref, vérifiez bien chaque type. Posez-vous la question : est-ce que cette variable est du texte ? Est-ce que je vais calculer dessus ? Est-ce que ce sont des catégories ? »
Vérification des doublons
Un des premiers réflexes à avoir dans toute opération de nettoyage : vérifier les doublons. Il peut s’agir :
de doublons complets (lignes identiques sur toutes les colonnes),
de doublons partiels (même identifiant, mais des valeurs légèrement différentes ailleurs).
Commencez par détecter les doublons complets avec :
Alex : « Deux clients avec le même numéro, c’est louche. Regarde ce qui se passe. Supprimer aveuglément n’est pas toujours la bonne solution. Note bien ce que tu fais dans le journal_nettoyage ! »
Et bien sûr, si vous intervenez, n’oubliez pas de l’indiquer dans la section DF de votre journal_nettoyage. Si vous ne trouvez aucun doublon, vous pouvez simplement noter dans votre texte que la vérification a été faite et qu’aucune suppression n’était nécessaire.
journal_nettoyage$DF<-append(journal_nettoyage$DF, list(list( id =c(101, 102), variables ="Toutes les colonnes", probleme ="Doublons complets", action ="Lignes supprimées", justification ="Exemple illustratif: à adapter seulement si des doublons sont détectés")))
Nettoyage des facteurs avec forcats
On continue l’exploration avec un type de variable souvent négligé… mais qui peut faire dérailler toute une analyse : les facteurs.
En R, les facteurs sont utilisés pour représenter des catégories. Par exemple, dans la colonne vehicle_type, chaque valeur correspond à un type de véhicule : "CAR", "TRUCK", "VAN", "ANIMAL", etc.
Pour voir l’ensemble des niveaux d’un facteur, vous pouvez utiliser la fonction levels() :
Bien sûr, il faut que votre variable soit de type factor pour que cette fonction fonctionne. Si ce n’est pas le cas, vous pouvez la convertir avec as.factor() (voir section précédente).
Le problème ?
Quand on regarde les niveaux d’un facteur, on remarque souvent des doublons déguisés ("car" vs "CAR"), des niveaux aberrants ("ANIMAL") ou des catégories très rares qui ne méritent peut-être pas leur propre niveau.
Quelques outils utiles (avec forcats)
Pour nettoyer tout ça, voici quelques fonctions clés du package forcats :
fct_count() : pour compter les niveaux et repérer les anomalies
fct_recode() : pour renommer des niveaux (par exemple fusionner "CAR" et "car")
fct_collapse() : pour fusionner plusieurs niveaux en un seul
fct_lump() : pour regrouper les niveaux rares en “Autre”
mêmes valeurs avec casse différente ("CAR" vs "car") dans certains fichiers
fautes de frappe ou variantes de saisie
niveaux aberrants ("ANIMAL" dans vehicle_type)
Alex : « Faites attention à ces valeurs étranges. Si une valeur n’a aucun sens dans le contexte (par exemple "ANIMAL" dans une colonne sur les types de véhicules), ne cherchez pas à deviner. Mettez-la à NA. On préfère une donnée manquante qu’une mauvaise information. »
Exemple à adapter
# Harmoniser les minuscules/majusculesbase<-base%>%mutate( vehicle_type =vehicle_type%>%str_to_title()%>%# "CAR" -> "Car", "TRUCK" -> "Truck"na_if("Animal")%>%# niveau aberrant dans ce contexteas_factor())
Vous pouvez repérer la ligne concernée avant la correction :
Il ne faudra pas oublier de documenter ces modifications dans votre liste journal_nettoyage ! Par exemple, pour la variable vehicle_type ci-dessus, vous pourriez ajouter :
journal_nettoyage$RC<-append(journal_nettoyage$RC, list(list( id =40064548, variables ="vehicle_type", probleme ="Niveau aberrant dans une variable de type de véhicule", action ="Remplacement de 'ANIMAL' par NA après harmonisation de la casse", justification ="La valeur ne décrit pas un type de véhicule exploitable")))
Ce ne sont que des exemples. À vous d’explorer la base de données et de choisir ce qui est cohérent.
Recette de nettoyage — Approfondissement
Bravo ! Vous avez déjà corrigé les types de variables et nettoyé les facteurs les plus visibles. Maintenant, on pousse le nettoyage plus loin, en croisant statistiques, relations logiques et comportements aberrants. Voici votre recette de nettoyage avancé.
Étape 1 – Statistiques descriptives sur les variables numériques
Tout comme on a vérifié les niveaux des facteurs, on doit vérifier si certaines valeurs numériques sont aberrantes.
Prenez chaque variable numérique et résumez-la avec summary() ou un boxplot pour identifier les extrêmes.
Exemple : commute_distance
summary(base$commute_distance)ggplot(base, aes(x =commute_distance))+geom_histogram(bins =50, fill ="blue", alpha =0.7)+labs(title ="Distribution de la distance de trajet domicile-travail", x ="Distance (km)", y ="Fréquence")
Posez-vous la question : une distance de 150 km pour se rendre au travail est-elle plausible ou simplement rare ? Est-ce que certaines valeurs sont manquantes ou négatives ?
Si vous intervenez, n’oubliez pas de justifier dans journal_nettoyage, en utilisant le code VA (valeurs aberrantes) ou VM (valeurs manquantes).
Étape 2 – Combinaisons incohérentes de deux facteurs
Il peut exister des relations logiques entre deux variables catégoriques. Par exemple, le trimestre (quarter) et la saison (season) devraient être cohérents.
Alex : « Si tu vois quarter = "Q2" avec season = "Winter", tu devrais tiquer… Ce genre d’incohérence mérite d’être noté, même si tu ne sais pas quoi corriger. »
Vous pouvez aussi visualiser avec un graphique à barres croisé :
ggplot(base, aes(x =quarter, fill =season))+geom_bar(position ="fill")
Si vous corrigez, utilisez le code CI (incohérences inter-variables).
Est-ce qu’il y a des points au-dessus d’une ligne où years_licensed = age ?
Peut-on avoir plus d’années de permis que d’âge ?
Alex : « Tu n’es pas obligé de corriger ici. Par contre, si tu remarques quelque chose d’étrange, prends deux minutes pour l’écrire dans le journal_nettoyage. Juste pour montrer que tu l’as vu, réfléchi, et que tu as pris une décision. C’est ça être rigoureux. »
Utilisez ici le code LG pour une erreur logique.
Étape 5 – Vérifications avancées (facultatives mais pros !)
Voici quelques autres choses à garder à l’œil :
Codes postaux incomplets ou trop longs : la colonne fsa_code devrait contenir trois caractères.
Années de véhicule improbables : une valeur comme 14 dans vehicle_year n’a pas le même sens que 2014.
Variables redondantes : deux colonnes qui disent la même chose.
Colonnes inutiles : identifiants internes, colonnes vides ou avec une seule modalité (EC ou RU)
Problèmes de format de texte : accents, caractères spéciaux (stringr::str_detect)
Colonnes fusionnées à la hâte : chaînes comme "Smith, John" dans une seule cellule au lieu de deux (TR)
Format de dates mélangés : on a laissé cela de côté depuis le début de ce cours, mais sachez que cela s’en vient, nous aurons un module spécial sur les dates.
Tout au long de votre nettoyage, documentez vos décisions dans la liste journal_nettoyage. Le but n’est pas de tout corriger, mais de montrer que vous avez su repérer les problèmes, réfléchir, et intervenir quand nécessaire.
Trace portfolio
Documentez ce qui rend votre nettoyage défendable et reproductible.
le fichier journal_nettoyage.Rdata;
le fichier donnees_propres.csv;
deux exemples de correction et un exemple de signalement sans correction automatique;
une courte explication de la façon de reproduire le nettoyage.
Mission accomplie !
Bravo d’être allé·e jusqu’au bout de cette aventure !
Vous avez maintenant acquis une solide méthodologie pour nettoyer des données de manière rigoureuse et professionnelle. Vous avez :
identifié et corrigé des erreurs de format, de type et de cohérence ;
utilisé les outils de dplyr, stringr, forcats et ggplot2 pour explorer les données sous toutes leurs coutures ;
documenté chaque intervention dans une structure claire et transparente avec la liste journal_nettoyage.
Avant de terminer, n’oubliez pas de pousser sur GitHub les trois éléments suivants :
Le script .qmd de votre aventure (là où vous avez effectué vos tests, analyses et nettoyage)
La liste journal_nettoyage enregistrée dans un objet .Rdata
La base de données nettoyée au format .csv
Pour sauvegarder votre liste dans un fichier .Rdata, utilisez simplement ce code à la fin de votre script :
Alex : « Vous venez de faire ce que peu de gens font bien : nettoyer des données proprement, en gardant une trace de vos décisions. C’est ce qui distingue un·e vrai·e professionnel·le de quelqu’un qui bidouille. Chapeau ! »
Comment réussir cette aventure ?
À la fin de cette aventure, vous devrez :
donnees_propres.csv).journal_nettoyagedans votre script.journal_nettoyage.Rdata.