Profiler avant de modifier
- Leçon 10
- 55 min
- Module 4 : Nettoyer et transformer les données
Leçon 10 sur 18 · SQL et préparation des données pour l'IAProfiler avant de modifier
1. Sources et structure des données
2. L'essentiel de SQL
3. Des requêtes d'analyse utiles
4. Nettoyer et transformer les données
5. Préparer la modélisation sans risque
6. Contrats de données et passation
Ce que vous saurez faire
Mesurez les problèmes dans les données avant de modifier une valeur. Si vous nettoyez d’abord, vous ne pourrez pas dire ensuite ce que vous avez changé, combien de lignes cela touchait, ni pourquoi.
Carnet JupyterFaites cette leçon dans un carnet Jupyter
Le carnet (notebook) Jupyter contient toutes les requêtes, tâches et vérifications de cette leçon, avec les instructions. Ses cellules de préparation installent pandas, créent la base de données et produisent l’extrait du module 3. Il ne nécessite donc aucune préparation locale. Lisez les explications ici et exécutez le code là-bas.
Le carnet est en anglais. Colab et Kaggle ouvrent votre propre copie. Il faut un compte Google ou Kaggle gratuit. Vous êtes bloqué ? Consultez le carnet de solution.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
COUNT(*),COUNT(column),GROUP BYetIS NULL, vus dans Agréger correctement.- Les jointures et les 14 identifiants de billets répétés, vus dans Joindre des tables.
- Ce que l’extrait sélectionne et pourquoi il contient 1 416 lignes, vus dans Une extraction reproductible.
- Comment créer un environnement virtuel et installer un paquet avec pip, vus dans Isoler les dépendances : exemple détaillé. Cette leçon en crée un pour le projet.
Ce qu’il vous faut sur votre ordinateur (seulement pour le parcours local; le carnet et les encadrés de cette page n’en ont pas besoin)
- Le dossier
~/projects/ticket-dataaveclarkfield.dbetq.py. Vous l’avez créé dans Préparer une base de données d’exercice : créer la base de données. Si la base de données manque ou a changé, réinitialisez-la avecpython3 get_data.py --reset. - L’extrait
data/extract/tickets.csv(1 416 lignes), produit parpython3 scripts/extract.py(sous Windows,python scripts/extract.py). Vous l’avez créé dans Une extraction reproductible : exercice guidé. Si le script manque ou ne fonctionne plus, récupérez les scripts terminés du cours. Copiezscripts/extract.pyet les deux fichiers dequeries/dans votre projet, puis exécutez le script à nouveau. - Un terminal ouvert dans ce dossier et une connexion Internet, une seule fois, pour installer pandas. Aucun compte ni paiement n’est nécessaire.
- Les requêtes enregistrées de ce module vont dans
queries/, avec une numérotation commençant par41-.
Testé sous macOS avec Python 3.14.6 et pandas 3.0.6. Les encadrés du navigateur utilisent SQLite 3.49.1. Les étapes Windows ne sont pas testées. Le carnet a été testé dans Jupyter.
Module 4 : de l’exportation à une table propre
Section intitulée « Module 4 : de l’exportation à une table propre »Larkfield est une boutique en ligne fictive de produits pour la maison et le jardin. Son service de soutien veut un modèle qui prédit, à l’arrivée d’un billet de soutien, s’il nécessitera un agent expérimenté. Dans les modules 1 à 3, vous avez interrogé l’exportation du service de soutien et enregistré un extrait reproductible. Dans ce module, Mei, l’ingénieure de données, nettoie cet extrait. Les données sont inventées pour ce cours; elles ne contiennent aucune personne réelle.
Le module comporte trois étapes, une par leçon :
- Profiler les données : trouver et compter chaque problème. Ne rien changer. (Cette leçon.)
- Charger les données dans Python avec les bons types, puis les joindre et les convertir en étapes nommées. (Leçon 2.)
- Décider quoi faire avec chaque problème, conserver les valeurs originales et rendre compte de chaque ligne. (Leçon 3.)
Qu’est-ce qu’un profil?
Section intitulée « Qu’est-ce qu’un profil? »Un profil est une courte description d’un jeu de données, colonne par colonne. Il indique combien de valeurs manquent, quelles valeurs apparaissent, ainsi que les valeurs minimale et maximale. Vous le créez avant toute modification, pour deux raisons. D’abord, il vous montre les problèmes. Ensuite, il représente l’état « avant ». Après le nettoyage, vous comparez le résultat avec cet état.
Regardez d’abord cinq billets inventés. Chaque ligne contient un problème qui ne provoque pas d’erreur :
| ticket_id | channel | order_value | word_count | created_at | Problème |
|---|---|---|---|---|---|
| T-1 | 42.50 | 80 | 2026-03-02 | aucun | |
| T-2 | NULL | 45 | 2026-03-02 | une deuxième graphie de email (courriel); une valeur manquante |
|
| T-3 | chat | -1 | 120 | 2026-03-03 | -1 n’est pas un montant : c’est un code pour « inconnu » |
| T-3 | chat | -1 | 120 | 2026-03-03 | la même ligne deux fois |
| T-4 | web_form | 4250 | 31000 | 2036-03-04 | des cents, pas des dollars; un message très long; une année dans le futur |
Une requête sur cette table s’exécute sans erreur. AVG(order_value) renvoie un nombre. Mais ce nombre est faux, et rien ne vous l’indique. Un profil pose cinq questions, et chaque question détecte un type de problème :
| Question | Type de problème | Dans les cinq billets |
|---|---|---|
| Quelles valeurs manquent, et que signifie chaque valeur manquante? | valeurs manquantes | T-2 n’a pas de order_value |
| Une ligne ou une clé apparaît-elle plus d’une fois? | doublons | T-3 deux fois |
| Toutes les valeurs figurent-elles dans la liste des valeurs permises? | catégories invalides | Email à côté de email |
| Toutes les valeurs utilisent-elles la même unité? | unités incohérentes | 4 250 cents à côté de 42,50 dollars |
| Les valeurs sont-elles dans une plage raisonnable? | plages suspectes | 31 000 mots, l’année 2036, -1 |
Le profil ne fait que trouver et compter. Les décisions viennent à la leçon 3. Certaines décisions nécessitent une personne qui connaît les activités de l’entreprise. Chez Larkfield, cette personne est Grace, la responsable du soutien.
Exemple détaillé : Mei profile l’exportation
Section intitulée « Exemple détaillé : Mei profile l’exportation »Mei profile l’exportation complète dans larkfield.db (1 417 lignes de billets), pas seulement l’extrait. L’extrait a exclu une ligne. Le profil doit aussi montrer cette ligne.
1. Valeurs manquantes
Section intitulée « 1. Valeurs manquantes »COUNT(*) compte les lignes. COUNT(column) compte les valeurs qui ne sont pas NULL. (NULL est le marqueur SQL qui signifie « aucune valeur ici ».) Donc, COUNT(*) - COUNT(column) donne le nombre de valeurs manquantes. Faites d’abord une prédiction : quelle colonne contient le plus de NULL?
Exécutez du SQL dans votre navigateur
Essayez : compter les valeurs manquantes
Exécutez la requête. Vous devriez voir 1 ligne : 1 417 lignes, puis 12, 38, 188, 0 et 12 valeurs manquantes.
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
Quatre colonnes contiennent des valeurs manquantes. Un compte seul ne suffit pas : le profil doit aussi indiquer ce que chaque NULL signifie. Mei interroge Grace sur chacune :
| Colonne | Lignes NULL | Ce que NULL signifie (Grace) |
|---|---|---|
customer_id |
12 | Un achat sans compte. Le client n’a pas de compte. |
channel |
38 | Le service de soutien n’a pas enregistré le canal. Il est inconnu. |
order_value |
188 | ? Mei vérifie ce cas dans le prochain encadré. |
closed_at |
12 | Le billet est encore ouvert. |
Exécutez du SQL dans votre navigateur
À vous : quels billets n'ont pas de montant de commande?
Écrivez une requête qui regroupe par team les billets dont order_value est NULL. Rappelez-vous : IS NULL, pas = NULL. La vérification compare votre résultat au nôtre.
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
Afficher la réponse
SELECT team, COUNT(*) AS nFROM ticketsWHERE order_value IS NULLGROUP BY team;Une ligne : account (compte), 188. L’équipe account compte 188 billets au total. Donc, chaque billet lié aux comptes a un order_value NULL, et aucun autre billet n’en a. Grace explique : « Les questions sur les comptes, comme la réinitialisation d’un mot de passe, n’ont pas de commande. » Ici, NULL n’est pas une valeur inconnue. Il signifie « il n’y a pas de commande ». Cette différence compte à la leçon 3.
2. Valeurs manquantes qui ne sont pas NULL
Section intitulée « 2. Valeurs manquantes qui ne sont pas NULL »Un système peut aussi marquer une valeur manquante par une valeur d’apparence normale, comme -1, 0, 9999 ou le texte N/A (sans objet). C’est une valeur sentinelle : une valeur qui représente « aucune valeur réelle ». Un compte des NULL ne la détecte pas. Les valeurs les plus fréquentes la révèlent souvent :
Exécutez du SQL dans votre navigateur
Essayez : les montants de commande les plus fréquents
Exécutez la requête. La première ligne est NULL (188 lignes). La deuxième ligne est -1, avec 11 lignes. Les montants réels apparaissent au plus 3 fois chacun.
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
Une commande ne peut pas coûter moins un dollar. Grace le confirme : le système de commandes écrit -1 lorsqu’il ne trouve pas la commande. Le profil contient donc deux types de order_value manquants : 188 NULL qui signifient « aucune commande » et 11 sentinelles qui signifient « commande inconnue ».
3. Doublons : lignes identiques et clés répétées
Section intitulée « 3. Doublons : lignes identiques et clés répétées »Il existe deux types de doublons. Un doublon exact est une ligne identique à une autre dans toutes les colonnes. Une clé répétée est une clé, ici ticket_id, qui apparaît dans plusieurs lignes, même si d’autres colonnes diffèrent. Vous avez rencontré les 14 identifiants de billets répétés au module 1. Le profil doit aussi préciser leur type.
Exécutez du SQL dans votre navigateur
Essayez : deux types de doublons
Exécutez la requête. Vous devriez voir 1 417 lignes, 1 403 identifiants distincts et 1 403 lignes distinctes.
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
SELECT DISTINCT * supprime seulement les doublons exacts. Il donne 1 403 lignes, soit le même nombre que les identifiants distincts. Les 14 lignes supplémentaires sont donc toutes des copies exactes. (Une page d’exportation a été envoyée deux fois.) C’est le cas simple : supprimer une copie ne fait perdre aucune information. Si les deux comptes différaient, certains billets auraient deux lignes différentes, et vous devriez décider laquelle est correcte.
4. Catégories invalides
Section intitulée « 4. Catégories invalides »Une colonne de catégories doit utiliser une liste fixe de valeurs. Pour channel, la liste est email, chat (clavardage), phone (téléphone) et web_form (formulaire Web).
Exécutez du SQL dans votre navigateur
Essayez : toutes les valeurs de canal
Exécutez la requête. Vous devriez voir 9 lignes. Trouvez les valeurs qui ne figurent pas dans la liste de quatre.
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
La liste de quatre, plus NULL, représente 1 377 lignes (541 + 413 + 200 + 185 + 38). Les 40 autres lignes utilisent quatre autres graphies : Email (20), chat avec une espace au début (8), EMAIL (7) et webform (5). Dans la table de résultats, l’espace dans chat est difficile à voir. GROUP BY l’affiche sur une ligne séparée, donc vous savez que la valeur est différente.
Exécutez du SQL dans votre navigateur
À vous : les segments dans la table des clients
Les segments permis sont home (particuliers), trade (professionnels) et business (entreprises). Écrivez une requête qui liste chaque graphie et son compte. Quelle graphie n’est pas permise?
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
Afficher la réponse
SELECT segment, COUNT(*) AS nFROM customersGROUP BY segmentORDER BY n DESC;Quatre lignes : home 166, trade 47, business 24, Trade 3. Trade est le même segment que trade, avec une majuscule.
5. Unités incohérentes
Section intitulée « 5. Unités incohérentes »Une colonne peut avoir un seul nom et deux unités. Pour le détecter, comparez des groupes. Si les valeurs d’un groupe sont environ 100 fois plus grandes que les autres, soupçonnez une unité différente. Mei regroupe les billets web_form par mois :
Exécutez du SQL dans votre navigateur
Essayez : les montants de commande du formulaire Web par mois
Exécutez la requête. Regardez janvier. Ensuite, remplacez 'web_form' par 'email' et exécutez-la à nouveau. Voyez-vous le même saut?
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
En janvier, la commande moyenne du formulaire Web est de 7 957,91 dollars. De février à juin, elle se situe entre 88,76 et 158,07 dollars. (La dernière ligne, 2036-01, correspond à un billet dont l’année est incorrecte. Vous le verrez dans la prochaine vérification.) Les commandes par courriel restent entre environ 100 et 145 dollars chaque mois. Grace connaît la raison : jusqu’au 1er février 2026, l’ancien formulaire Web envoyait le montant en cents. 4 503 cents représentent 45,03 dollars. Un modèle qui voit ces valeurs apprend que les clients du formulaire Web achètent des choses chères, ce qui est faux.
6. Plages suspectes
Section intitulée « 6. Plages suspectes »Les valeurs minimale et maximale de chaque colonne révèlent des valeurs impossibles ou très improbables.
Exécutez du SQL dans votre navigateur
Essayez : les valeurs minimale et maximale
Exécutez la requête. Vous devriez voir 4 lignes. Pour chaque ligne, demandez-vous : « Cette valeur est-elle possible? »
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
| Colonne | Minimum | Maximum | Ce que Mei trouve |
|---|---|---|---|
created_at |
2026-01-05 07:30:24 | 2036-01-24 21:27:43 | Un billet est daté de 10 ans dans le futur. Il a été fermé le 25 janvier 2026, donc quelqu’un a saisi 2036 au lieu de 2026. L’extrait exclut cette ligne. |
priority |
1 | 3 | Comme prévu. |
order_value |
-1 | 34518 | Encore la sentinelle et les cents. 25 valeurs dépassent 2 000. Parmi elles, 24 sont des billets du formulaire Web de janvier; la 25e est le billet de 2036, aussi du formulaire Web. |
word_count |
0 | 48210 | Grace : 0 mot correspond à un billet contenant seulement une pièce jointe (7 lignes, valides). 48 210 mots correspondent à un billet, T-10361, où le client a collé un fichier de journaux (logs). |
Certains problèmes sont visibles seulement quand vous comparez deux tables. Un billet ne peut pas exister avant le compte du client :
Exécutez du SQL dans votre navigateur
À vous : les billets antérieurs au client
Ajoutez une clause WHERE qui conserve un billet seulement si sa date précède joined_on. Prédisez d’abord le nombre de lignes.
Tab ajoute quatre espaces. Appuyez sur Esc, puis sur Tab, pour quitter la zone. Ctrl+Enter exécute la requête. Chaque exécution part d’une nouvelle copie de la base de données d’exercice.
Afficher la réponse
SELECT t.ticket_id, t.customer_id, t.created_at, c.joined_onFROM tickets AS tJOIN customers AS c ON c.customer_id = t.customer_idWHERE date(t.created_at) < c.joined_on;3 lignes : T-11185 (créé le 25 mars 2026, inscription le 5 avril 2026), T-11224 (17 mai 2026, inscription le 24 mai 2026) et T-11375 (23 mars 2026, inscription le 10 avril 2026). Soit la date du billet, soit la date d’inscription est incorrecte, et les données ne précisent pas laquelle. Mei ne peut pas corriger ces lignes avec certitude.
Exécuter le profil sur votre ordinateur
Section intitulée « Exécuter le profil sur votre ordinateur »Les encadrés ci-dessus utilisent le navigateur. Mei enregistre les requêtes de profil dans son projet pour les réexécuter sur une nouvelle exportation. Ouvrez un terminal dans ~/projects/ticket-data. Enregistrez ce fichier sous queries/41-profile-missing.sql :
-- Profile: missing values in tickets (NULL count per column).SELECT COUNT(*) AS ticket_rows, COUNT(*) - COUNT(customer_id) AS no_customer_id, COUNT(*) - COUNT(channel) AS no_channel, COUNT(*) - COUNT(order_value) AS no_order_value, COUNT(*) - COUNT(word_count) AS no_word_count, COUNT(*) - COUNT(closed_at) AS no_closed_atFROM tickets;python3 q.py queries/41-profile-missing.sqlpython q.py queries/41-profile-missing.sqlpython3 q.py queries/41-profile-missing.sqlticket_rows no_customer_id no_channel no_order_value no_word_count no_closed_at----------- -------------- ---------- -------------- ------------- ------------1417 12 38 188 0 12
1 rowEnregistrez les autres vérifications de la même façon, une requête par fichier : 42-profile-ranges.sql pour les valeurs minimale et maximale, et ainsi de suite. (Utilisez les prochains numéros libres dans votre dossier queries/ si vos numéros diffèrent.)
Le même profil dans pandas
Section intitulée « Le même profil dans pandas »Le reste de ce module utilise pandas, une bibliothèque Python pour les tables. Une table pandas est un DataFrame : des lignes et des colonnes nommées, comme une table SQL, mais en mémoire dans votre programme Python. pandas ne fait pas partie de Python. Vous l’installez donc maintenant dans un environnement virtuel pour ce projet.
cd ~/projects/ticket-datapython3 -m venv .venvsource .venv/bin/activatepython -m pip install pandas==3.0.6cd ~/projects/ticket-datapython -m venv .venv.venv\Scripts\Activate.ps1python -m pip install pandas==3.0.6cd ~/projects/ticket-datapython3 -m venv .venvsource .venv/bin/activatepython -m pip install pandas==3.0.6Successfully installed numpy-2.5.3 pandas-3.0.6 python-dateutil-2.9.0.post0 six-1.17.0L’invite de commande commence maintenant par (.venv). À partir d’ici, le cours utilise python sur tous les systèmes, car l’activation fait pointer python vers l’environnement. q.py fonctionne toujours avec lui : il nécessite seulement la bibliothèque standard.
Écrivez à la main la version choisie dans requirements.txt, pour qu’un nouvel environnement obtienne la même version de pandas :
pandas==3.0.6Le profil pandas de Mei lit l’extrait, data/extract/tickets.csv. C’est le fichier utilisé par l’étape de nettoyage. Enregistrez-le sous scripts/profile.py :
"""Profile the extracted tickets. Print counts; change nothing."""
import pandas as pd
df = pd.read_csv("data/extract/tickets.csv")print(f"Rows: {len(df)}")
missing = df.isna().sum()print("\nMissing values (columns with at least one):")print(missing[missing > 0])
print(f"\nExact duplicate rows: {df.duplicated().sum()}")print(f"Rows with a ticket_id seen before: {df.duplicated(subset='ticket_id').sum()}")
print("\nChannel values:")print(df["channel"].value_counts(dropna=False))
print("\nRanges:")print(df[["order_value", "word_count"]].describe().round(2))print(f"\norder_value = -1: {(df['order_value'] == -1).sum()}")print(f"order_value > 2000: {(df['order_value'] > 2000).sum()}")print(f"word_count > 10000: {(df['word_count'] > 10000).sum()}")| Code | Ce qu’il fait | Équivalent en SQL |
|---|---|---|
pd.read_csv(...) |
Lit le fichier CSV dans un DataFrame. | la table |
df.isna().sum() |
Compte les valeurs manquantes dans chaque colonne. | COUNT(*) - COUNT(col) |
df.duplicated() |
Marque chaque ligne qui est une copie exacte d’une ligne précédente. .sum() les compte. |
COUNT(*) moins SELECT DISTINCT * |
df.duplicated(subset='ticket_id') |
Fait la même chose, mais compare seulement ticket_id. |
COUNT(*) - COUNT(DISTINCT ticket_id) |
value_counts(dropna=False) |
Compte chaque valeur et inclut les valeurs manquantes. | GROUP BY channel |
describe() |
Compte, moyenne, écart-type, minimum, quartiles et maximum. | MIN, MAX, AVG |
python scripts/profile.pyRows: 1416
Missing values (columns with at least one):customer_id 12channel 38order_value 188closed_at 12segment 21region 139joined_on 21dtype: int64
Exact duplicate rows: 14Rows with a ticket_id seen before: 14
Channel values:channelemail 541chat 413web_form 199phone 185NaN 38Email 20 chat 8EMAIL 7webform 5Name: count, dtype: int64
Ranges: order_value word_countcount 1228.00 1416.00mean 272.09 142.13std 1262.66 1280.38min -1.00 0.0025% 50.28 59.0050% 88.79 91.0075% 164.89 134.25max 22394.00 48210.00
order_value = -1: 11order_value > 2000: 24word_count > 10000: 1Comparez-le au profil SQL. Tout compter inclut les différences :
- 1 416 lignes, pas 1 417 : l’extrait a exclu le billet de 2036. Ce billet était un billet
web_formde 34 518 cents. Donc,web_formcompte ici 199 lignes, pas 200, etorder_value > 2000donne 24, pas 25. - pandas affiche une valeur manquante sous la forme
NaN(« pas un nombre »). segment,regionetjoined_onviennent de la jointure avec les clients dans l’extrait. Ces valeurs manquent pour 21 lignes : les 12 billets sans compte et les 9 billets dont le client est absent de la table des clients.regioncontient 118 valeurs manquantes supplémentaires, car 9 clients n’ont pas de région.- La moyenne de
order_valueest de 272,09 dollars, mais la médiane (50%) est de 88,79. Les cents et les valeurs-1influencent la moyenne. Ne présentez pas cette moyenne.
Exercice guidé : rédiger le profil
Section intitulée « Exercice guidé : rédiger le profil »Le profil est un document, pas seulement une sortie dans un terminal. Priya, la scientifique de données, le lit avant d’entraîner un modèle. Grace vérifie les significations.
- Créez le dossier
reportsdans votre projet, s’il n’existe pas. - Créez le fichier
reports/profile.md. - Écrivez la source en haut : le fichier, son nombre de lignes et la date de l’instantané
2026-07-01 06:00. - Ajoutez une section pour chacune des cinq questions. Dans chaque section, écrivez le compte et la requête ou le code qui le produit.
- Pour chaque valeur manquante et chaque valeur étrange, écrivez ce qu’elle signifie. Si vous ne savez pas, écrivez la question pour Grace.
- Ajoutez une dernière section, « Pas encore décidé ». Listez chaque problème sans correction.
- Exécutez
python scripts/profile.pyà nouveau et comparez chaque nombre de votre profil avec la sortie.
Afficher un exemple de profil
# Profile: Larkfield tickets
Source: data/extract/tickets.csv, 1,416 rows (larkfield.db has 1,417;the extract leaves out 1 ticket created in 2036). Snapshot 2026-07-01 06:00.Made with queries/41-profile-missing.sql, 42-profile-ranges.sqland scripts/profile.py. Nothing changed.
## Missing values| Column | Rows | Meaning (checked with Grace) ||-------------|------|--------------------------------------------------|| customer_id | 12 | guest checkout, no account || channel | 38 | not recorded: unknown || order_value | 188 | all account tickets: there is no order || order_value | 11 | value -1: the order system could not find it || closed_at | 12 | ticket still open || segment, region, joined_on | 21 | no customer row (12 guests, 9 deleted) || region | 118 more | the customer gave no region |
## Duplicates14 rows are exact copies (export page overlap). Same count by ticket_id,so no ticket has two different rows. 1,402 rows stay after removing them.
## Categorieschannel: 40 rows use other spellings (Email 20, " chat" 8, EMAIL 7, webform 5).segment (customers): Trade 3 next to trade 47.
## Unitsorder_value: web form tickets before 2026-02-01 are in cents (24 rows:23 "web_form", 1 "webform"; January average 7,957.91). From February theweb form sends dollars.
## Rangesword_count: 0 in 7 rows (attachment only: valid); 48,210 in T-10361 (log file).created_at: 3 tickets before the customer's joined_on date(T-11185, T-11224, T-11375). Which date is wrong is not known.
## Not decided yet- What to do with the 3 tickets created before the customer joined.- What to do with T-10361.- How to treat the 11 unknown order values in the model.À vous de jouer : profiler les événements de résultat
Section intitulée « À vous de jouer : profiler les événements de résultat »Profilez la table outcomes avec les cinq mêmes questions. Utilisez la zone du navigateur ci-dessus (modifiez la requête) ou q.py. Faites d’abord une prédiction : outcomes contient-elle des lignes exactement identiques?
Afficher le profil attendu
- Lignes : 1 874.
- Valeurs manquantes :
resolution_codevaut NULL dans 341 lignes. Seuls les événementsresolved(résolus) ont un code (1 533 sur 1 533). Les événementsescalated(transférés au niveau supérieur) etreopened(rouverts) n’en ont aucun. NULL signifie donc « pas encore résolu dans cet événement ».csatvaut NULL dans 959 lignes; seuls les événementsresolvedont cette valeur (915 valeurs). Un client ne répond pas toujours au sondage. - Doublons : aucun doublon exact (1 874 lignes distinctes, 1 874 valeurs distinctes de
outcome_id). MaisSELECT DISTINCT ticket_id, recorded_at, statusdonne 1 844 lignes : 30 événements ont été enregistrés deux fois, avec un nouveauoutcome_id. Ici, la clé n’est pas l’identifiant. La recherche de doublons doit utiliser les colonnes qui décrivent l’événement. - Enregistrements orphelins : 4 événements appartiennent à des billets absents de
tickets. - Catégories :
statusa 3 valeurs, etresolution_codeen a 4, plus NULL. Toutes sont permises. - Plages :
csatva de 1 à 5.recorded_atva jusqu’au 1 juillet 2026 à 5 h 41 min 45 s, avant l’instantané. Un événement (O-00193) précède lecreated_atde son billet : il appartient au billet de 2036,T-10147. La date incorrecte est donc celle du billet.
Erreur courante
Le profil indique 188 montants de commande manquants. Il y en a 199.
Symptôme : le profil compte les valeurs manquantes avec df.isna().sum() ou COUNT(*) - COUNT(order_value) et en indique 188. Le montant moyen des commandes semble un peu bas, mais rien ne plante.
Cause : les 11 valeurs -1 sont des valeurs sentinelles. Pour SQL et pandas, ce sont des nombres ordinaires. Le décompte des NULL ne les détecte pas. AVG et mean() les traitent comme un montant de moins un dollar.
Solution :
- Examinez les valeurs les plus petites et les plus fréquentes de chaque colonne numérique, pas seulement le décompte des NULL.
- Cherchez les valeurs sentinelles courantes :
-1,0,999,9999, et des textes commeN/A(sans objet),none(aucun) ouunknown(inconnu). - Demandez au responsable des données ce que chacune signifie, et notez la réponse dans le profil.
Dans le travail en IA : un modèle entraîné sur -1 apprend que certaines commandes coûtent moins un dollar. Pire encore, si « commande inconnue » est lié au transfert au niveau supérieur, le modèle associe ce transfert à une très petite commande. Ce n’est pas vrai.
Vérifiez votre compréhension
La table tickets contient 1 417 lignes et 1 403 identifiants de billet distincts. SELECT DISTINCT * donne aussi 1 403 lignes. Qu'est-ce que cela vous apprend sur les doublons? Que signifierait un résultat de 1 410 lignes avec SELECT DISTINCT *?
Afficher la réponse
Les 14 lignes supplémentaires sont toutes des copies exactes. Vous pouvez donc les supprimer sans rien perdre. Avec 1 410 lignes distinctes, 7 des identifiants répétés auraient des lignes différentes dans au moins une colonne. Certains billets auraient alors deux versions. Vous devez trouver la bonne version avant d’en supprimer une.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
order_value vaut NULL dans 188 lignes et -1 dans 11 lignes. Ces 199 lignes signifient-elles la même chose?
Afficher la réponse
Non. Les 188 NULL correspondent exactement aux billets concernant les comptes : il n’y a aucune commande, donc aucun montant à trouver. Les 11 valeurs -1 correspondent à des commandes qui existent, mais dont le système de commandes n’a pas trouvé le montant. La valeur est inconnue. Un profil doit distinguer ces cas, car leur traitement diffère.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Pourquoi le profil ne change-t-il rien, même quand une correction semble évidente, comme remplacer Email par email?
Afficher la réponse
Le profil est la photo « avant ». Si vous corrigez les valeurs pendant le profilage, vous ne pourrez pas compter ensuite les changements apportés par le nettoyage. De plus, le nettoyage ne sera pas regroupé dans un seul script reproductible. Certaines corrections évidentes sont aussi incorrectes : il faut parfois consulter le responsable métier pour comprendre une valeur.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Un profil pose cinq questions : valeurs manquantes, doublons, catégories invalides, unités incohérentes et plages suspectes. Il ne change rien.
- Un décompte ne suffit pas. Notez ce que signifie chaque valeur manquante : ici, un
order_valueNULL signifie « aucune commande », et-1signifie « inconnu ». - Comparez
COUNT(DISTINCT key)avecSELECT DISTINCT *pour distinguer les doublons exacts des clés répétées. - Repérez les unités mélangées en comparant les groupes, par exemple la moyenne par mois et par canal.
- L’extraction contient 1 416 lignes; le profil dans
reports/profile.mdexplique chaque problème avec un décompte.
Ensuite, vous chargez l’extraction dans pandas avec le bon type pour chaque colonne, afin que pandas n’ait pas à deviner.
Leçon suivante : Transformer avec Python